+-------------------+
| Metadata          |
+----------+--------+
| Template | guides |
+----------+--------+
| Category | Build  |
+----------+--------+

+-------------------+
| Section Metadata  |
+---------+---------+
| style   | content |
+---------+---------+

![White Adobe logo on a red square.][image0]

# How to use Sharepoint (application)

**NOTE**: for projects using Adobe’s Sharepoint please continue [here](https://main--adobe--helix-website.hlx.page/docs/setup-adobe-sharepoint).

If you use SharePoint as your content source, AEM uses a registered Microsoft Azure application to access your content. This application has **delegated permissions** defined that allow the service to access SharePoint on behalf of a user. This user needs to be registered to the project that is using SharePoint.

Alternatively, the services can also authenticate as an application and use **application permissions** to access the sites. This needs additional setup by a SharePoint site administrator that can grant the permissions for the application.

The preferred setup is to use **application permissions**, as this narrows down the access the service has to a specific SharePoint site and does not require to share any secrets of a technical user. Also, it reduces the problems around password rotation.

The following describes how to set up **application permissions** for your project. If you want to set up a technical user, please continue [here](https://main--adobe--helix-website.hlx.page/docs/setup-customer-sharepoint-user).

Setting up SharePoint involves the following steps:

1. Create or identify a Sharepoint site that will serve as site for the document based authoring
2. Create a folder within SharePoint that will be the website root.
3. Set the content source in your site configuration
4. Access the Registration Portal
5. Register the Application
6. Apply the `sites.selected` permission to the SharePoint site

## 1. Create or identify a Sharepoint site

Talk to your IT department to either identify or create a Sharepoint site that will be used for document based authoring. One site can “host” multiple websites (projects). This site will later receive the respective permissions so that the publishing services can access it.

## 2. Create the website root folder

Navigate to your desired location in the SharePoint site created or identified above and create a root folder that will be your website root. It is best to not use a SharePoint list root directly, so that you have a shared space for your authors to put collateral documents, for example a drafts folder, or how-to-author documentations.

An example file structure might look like this, using the `website` folder as the root:

![][image1]

## 3. Set the content source in your site configuration

The next step is to set the source property in your site configuration to the corresponding Sharepoint URL\
\
(see: <https://www.aem.live/docs/admin.html#schema/SiteConfig> for more detail)\
\
The expected format usually looks like the example below.

```
https://<tenant>.SharePoint.com/sites/<sp-site>/Shared%20Documents/website
```

\
This might vary depending on how you create the SharePoint site and lists. In order to obtain the url, the simplest way is to copy-past the first part from the browser address, eg:\
\
![][image2]

And then add the rest manually (Note, that copying the sharelink via the UI adds unnecessary information and it is better to use a canonical representation of the url). Once you compose the url, you can test it by entering it again in the browser. You should end up in the folder view of your website root.

After that, update the `source` in your site config service via the API accordingly.

An easy way to make this change is to use  `https://labs.aem.live/tools/site-admin/index.html`  to either create or update a site configuration.

For example:\
\
![][image3]\
\
Hit `save` to persist the change.

## 4. Access the Registration Portal

### Overview

In order for the AEM service to access the authored content it needs a couple of information and setup. The AEM service (a cloud function) accesses the [MS Graph API](https://learn.microsoft.com/en-gb/graph/) on behalf of an application (or configured user). In order to do so, it needs to authenticate first in the context of an [Application](https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/what-is-application-management). This is important because the scopes given to the application define what permission the service has on the MS Graph API. For example, it should be allowed to read and write documents, but not to alter access control.

An application is represented as an “Enterprise Application” in the respective Active Directory of a tenant. The permissions given to that enterprise application ultimately define what the service can access in that tenant’s resources. Certain permissions need to be approved by an Active Directory administrator before a user can use the application. This so-called “admin consent” is a mechanism to verify and control which permissions apps can have. This is to prevent dubious apps from tricking users into trusting an app that is not official. Having the extra admin consent step allows IT security to control which apps the employees can use.

## 1. Sign-in in the Registration Portal

+----------------------------------------------------------------------------------------------------+
| Columns (contained, fullscreen images)                                                             |
+--------------------------------------------------------------------------------+-------------------+
| ### View Enterprise Applications in Azure Portal                               | ![][image4]       |
|                                                                                |                   |
| Assuming that so far no AEM Enterprise Applications are present in Azure       |                   |
| (Microsoft Entra Id)                                                           |                   |
+--------------------------------------------------------------------------------+-------------------+
| ### Access The Registration Portal                                             | ![][image5]       |
|                                                                                |                   |
| Go to <https://admin.hlx.page/register>, enter the github url of the           |                   |
| project or the org/site values of your site config.                            |                   |
+--------------------------------------------------------------------------------+-------------------+
| ### Sign-in as non admin user                                                  | ![][image6]       |
|                                                                                |                   |
| Sign in as a user that **does not** have admin permissions will show an        |                   |
| error that it needs approval, i.e. the application needs admin consent.        |                   |
|                                                                                |                   |
| **Problem**: Enterprise Application is not registered if a user never logs in. |                   |
+--------------------------------------------------------------------------------+-------------------+
| ### Sign-in as admin user                                                      | ![][image7]       |
|                                                                                |                   |
| One solution is to sign in as a user that **does** have admin permissions:     |                   |
|                                                                                |                   |
| (note, at this point the Enterprise Application is still not registered in     |                   |
| azure)                                                                         |                   |
+--------------------------------------------------------------------------------+-------------------+
| ### AEM Content Integration Registration visible in UI                         | ![][image8]       |
|                                                                                |                   |
| If the admin logs in (without checking the checkbox and granting consent for   |                   |
| everyone), the Enterprise application is present.                              |                   |
+--------------------------------------------------------------------------------+-------------------+

### Create application using MSGraph or Powershell

Alternatively, you can create the Enterprise application via MSGraph or Powershell.

In order to make it visible in the azure UI you also need to add the `WindowsAzureActiveDirectoryIntegratedApp` tag. This can be done directly when creating the application.\
\
Using graph explorer:

```
POST https://graph.microsoft.com/v1.0/servicePrincipals
Content-type: application/json
{
    "appId": "e34c45c4-0919-43e1-9436-448ad8e81552",
    "tags": [
        "WindowsAzureActiveDirectoryIntegratedApp"
    ]
}
```

Using powershell:

```
PS> connect-MgGraph -Scopes "Application.ReadWrite.All"
PS> New-MgServicePrincipal -AppId e34c45c4-0919-43e1-9436-448ad8e81552 -Tags WindowsAzureActiveDirectoryIntegratedApp
```

+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
| Columns (contained, fullscreen images)                                                                                                                    |
+---------------------------------------------------------------------------------------------------------------------------------------+-------------------+
| After that you still need to give admin consent, if you want a non admin user to login.                                               | ![][image9]       |
|                                                                                                                                       |                   |
| \                                                                                                                                     | ![][image10]      |
| Also see:                                                                                                                             |                   |
|                                                                                                                                       | ![][image11]      |
| - <https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/create-service-principal-cross-tenant>                            |                   |
| - <https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/add-application-portal-configure?pivots=ms-graph>                 |                   |
+---------------------------------------------------------------------------------------------------------------------------------------+-------------------+
| ### Review permissions                                                                                                                | ![][image12]      |
|                                                                                                                                       |                   |
| Note that the `AEM Content Integration Registration (e34c45c4-0919-43e1-9436-448ad8e81552)` application is only                       |                   |
| needed during registration to verify that the user has read access to the sharepoint. It has the following **delegated permissions**: |                   |
|                                                                                                                                       |                   |
| - `Openid`\                                                                                                                           |                   |
|   Allows users to sign in to the app with their work or school accounts and allows the app to see basic user profile                  |                   |
|   information.                                                                                                                        |                   |
| - `Profile`\                                                                                                                          |                   |
|   Allows the app to see your users' basic profile (e.g., name, picture, user name, email address)                                     |                   |
| - `Files.ReadWrite.All`\                                                                                                              |                   |
|   Allows the app to read, create, update and delete all files the signed-in user can access.                                          |                   |
+---------------------------------------------------------------------------------------------------------------------------------------+-------------------+
| ### User logged in Registration portal                                                                                                | ![][image13]      |
|                                                                                                                                       |                   |
| After completing this initial step, the user is logged in the registration portal                                                     |                   |
+---------------------------------------------------------------------------------------------------------------------------------------+-------------------+

## Verify write access to the content source via challenge file

+-----------------------------------------------------------------------------------+
| Columns (contained, fullscreen images)                                            |
+---------------------------------------------------------------+-------------------+
| ### Download the challenge file                               | ![][image14]      |
|                                                               |                   |
| Before you can register (or change) the registration. You     | ![][image15]      |
| have to prove that you have write access to the respective    |                   |
| sharepoint location. For that you need to upload a text file  |                   |
| containing the mentioned content. This can easily be done by  |                   |
| downloading the file and drop it into the sharepoint folder.  |                   |
|                                                               |                   |
| After that, click on `Validate` to continue the registration. |                   |
+---------------------------------------------------------------+-------------------+

## Adding the AEM Content Integration App with application permissions

+-------------------------------------------------------------------------------------------------------------------+
| Columns (contained, fullscreen images)                                                                            |
+-----------------------------------------------------------------------------------------------+-------------------+
| ### Add Enterprise Application                                                                | ![][image16]      |
|                                                                                               |                   |
| When logged in the registration portal, the content source that is                            |                   |
| used by the project needs to be connected to an oauth grant for the `AEM Content Integration` |                   |
| application. This is needed, so that the system can access the                                |                   |
| documents in sharepoint and convert them to an internal format                                |                   |
| (markdown) and store it in Adobe’s storage (S3/R2) for fast delivery.                         |                   |
|                                                                                               |                   |
| Using application `sites.selected` permissions is more secure as it                           |                   |
| limits the scope to a single sharepoint site. In order to connect,                            |                   |
| click on the `Connect Application` button.                                                    |                   |
|                                                                                               |                   |
| If you never registered an application or a user before, you probably                         |                   |
| see the following error:                                                                      |                   |
|                                                                                               |                   |
| ```                                                                                           |                   |
| Unable to validate access: General exception while processing                                 |                   |
| ```                                                                                           |                   |
|                                                                                               |                   |
| or                                                                                            |                   |
|                                                                                               |                   |
| ```                                                                                           |                   |
| Unable to validate access: Either scp or roles claim                                          |                   |
| need to be present in the token.                                                              |                   |
| ```                                                                                           |                   |
+-----------------------------------------------------------------------------------------------+-------------------+

Same as above, the Enterprise application for the `AEM Content Integration (83ab2922-5f11-4e4d-96f3-d1e0ff152856)` is not present in Azure yet,\
\
In order to add it, use the graph explorer or powershell to add it:

\
Using graph explorer:

```
POST https://graph.microsoft.com/v1.0/servicePrincipals
Content-type: application/json
{
    "appId": "83ab2922-5f11-4e4d-96f3-d1e0ff152856",
    "tags": [
        "WindowsAzureActiveDirectoryIntegratedApp"
    ]
}
```

Using powershell:

```
PS> connect-MgGraph -Scopes "Application.ReadWrite.All"
PS> New-MgServicePrincipal -AppId 83ab2922-5f11-4e4d-96f3-d1e0ff152856 -Tags WindowsAzureActiveDirectoryIntegratedApp
```

\
\
Also see:

- <https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/create-service-principal-cross-tenant>

+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Columns (contained, fullscreen images)                                                                                                                              |
+-------------------------------------------------------------------------------------------------------------------------------------------------+-------------------+
| ### Add Application Roles                                                                                                                       | ![][image17]      |
|                                                                                                                                                 |                   |
| Now the enterprise application `AEM Content Integration` is visible in azure. But it doesn’t have any `Sites.Selected` application permissions. | ![][image18]      |
|                                                                                                                                                 |                   |
| **Problem**: Using the admin consent UI would grant all application and delegated permissions, which we don’t want.                             |                   |
|                                                                                                                                                 |                   |
| An easy way is to consent to all permissions and then remove the delegated ones again.                                                          |                   |
+-------------------------------------------------------------------------------------------------------------------------------------------------+-------------------+

### Add Application Roles using Powershell or Graph Explorer

Alternatively, adding the app roles can be done with the following steps:

1. Find the service principal of the enterprise application (`principalId`). This is the one you created above.
2. Find the service principal of the Microsoft Graph API (`resourceId`)
3. Find the Id for the `Sites.Selected `Application Role (`appRoleId`)
4. Assign the Application Role to the Managed Identity (The Enterprise Application)

Using **powershell** this can be done with:

```
$ObjectId = "abcdef-1234-49b6-b660-cc85b34fe516"    <<------ replace with your enterprise app id
$AAD_SP = Get-AzureADServicePrincipal -SearchString "Microsoft Graph";
$AAD_SP
 
$MSI = Get-AzureADServicePrincipal -ObjectId $ObjectId
if($MSI.Count -gt 1)
  { 
  Write-Output "More than 1 principal found, please find your principal and copy the right object ID. Now use the syntax $MSI = Get-AzureADServicePrincipal -ObjectId <your_object_id>"
  Exit
  }
 
$AAD_AppRole = $AAD_SP.AppRoles | Where-Object {$_.Value -eq "Sites.Selected"}
New-AzureADServiceAppRoleAssignment -ObjectId $MSI.ObjectId  -PrincipalId $MSI.ObjectId  -ResourceId $AAD_SP.ObjectId[0]  -Id $AAD_AppRole.Id

```

Using **graph explorer** it involves more steps:

1. Find the principal of the enterprise application for `AEM Content Integration` :

```
  GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId eq '83ab2922-5f11-4e4d-96f3-d1e0ff152856' 
...
  "value": [
        {
            "id": "6761ada0-733b-4a02-98b2-3db970834fe0",
...
```

This will be our `principalId`

1. Find the service principal of the Microsoft Graph API

```
GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId eq '00000003-0000-0000-c000-000000000000'
...
  "value": [
        {
            "id": "5159db96-7193-414e-9730-b1d1e4448443",
...
```

This is the `resourceId`. (the resource that defines the application role)

1. Find the id of the application role.\
   \
   `GET https://graph.microsoft.com/v1.0/servicePrincipals/${resourceId}/appRoles`

\
Substitute the `resourceId` with the service principal of the Microsoft Graph API  as obtained from the previous step.

```
GET https://graph.microsoft.com/v1.0/servicePrincipals/5159db96-7193-414e-9730-b1d1e4448443/appRoles
...
        {
            "allowedMemberTypes": [
                "Application"
            ],
            "description": "Allow the application to access a subset of site collections without a signed in user.  The specific site collections and the permissions granted will be configured in SharePoint Online.",
            "displayName": "Access selected site collections",
            "id": "883ea226-0bf2-4a8f-9f9d-92c9162a727d",
            "isEnabled": true,
            "origin": "Application",
            "value": "Sites.Selected"
        },
...
```

Find the entry for `Sites.Selected`. This Id is the `appRoleId`

1. Assign the Application Role to the Managed Identity. The request has the format:

```
POST https://graph.microsoft.com/v1.0/servicePrincipals/${principalId}/appRoleAssignedTo
Content-Type: application/json

{
  "principalId": "${principalId}",
  "resourceId": "${resourceId}",
  "appRoleId": "${appRoleId}"
}
```

For example:

```
https://graph.microsoft.com/v1.0/servicePrincipals/6761ada0-733b-4a02-98b2-3db970834fe0/appRoleAssignedTo
Content-type: application/json
{
    "principalId": "6761ada0-733b-4a02-98b2-3db970834fe0",
    "resourceId": "5159db96-7193-414e-9730-b1d1e4448443",
    "appRoleId": "883ea226-0bf2-4a8f-9f9d-92c9162a727d"
}
```

+-------------------------------------------------------------------------------+
| Columns (contained, fullscreen images)                                        |
+-----------------------------------------------------------+-------------------+
| ### Validate Permissions                                  | ![][image19]\     |
|                                                           | ![][image20]      |
| Eventually you should see the granted application         |                   |
| permission in the UI.                                     |                   |
|                                                           |                   |
| Back in the registration portal, they should have changed |                   |
| to:                                                       |                   |
|                                                           |                   |
| _The content source can't be found or you don't have      |                   |
| permission to access it. Please check that the URL is     |                   |
| correct, the app "AEM Content Integration                 |                   |
| (83ab2922-5f11-4e4d-96f3-d1e0ff152856)" has the right     |                   |
| permissions, and that the user is allowed to access it.._ |                   |
+-----------------------------------------------------------+-------------------+

### Add permissions to Sharepoint Site

In order to add the permissions to the sharepoint site, we need to find its `SiteId`.

This can be done using again the graph explorer:

```
GET https://graph.microsoft.com/v1.0/sites/{host-name}:/{server-relative-path}
```

\
Example:

```
GET https://graph.microsoft.com/v1.0/sites/adobeenterprisesupportaem.sharepoint.com:/sites/hlx-test-project

{
...
    "id": "adobeenterprisesupportaem.sharepoint.com,03cc3587-0e4d-405e-b06c-ffb0a622b7ac,5fbc1df5-640c-4780-8b59-809e3193c043",
...
}

```

Using the `Id` we can set the permissions:

```
POST https://graph.microsoft.com/v1.0/sites/adobeenterprisesupportaem.sharepoint.com,03cc3587-0e4d-405e-b06c-ffb0a622b7ac,5fbc1df5-640c-4780-8b59-809e3193c043/permissions
Content-type: application/json

{
    "roles": [
        "write"
    ],
    "grantedToIdentities": [
        {
            "application": {
                "id": "83ab2922-5f11-4e4d-96f3-d1e0ff152856",
                "displayName": "AEM Content Integration"
            }
        }
    ]
}
```

\
**Note:** If you get an “Access Denied” error while executing the above request **,** you need to have “Site Admin” permissions in order to run the above step. Also you may need to give additional “consent” from the Graph Explorer’s “Modify Permissions” panel for  additional “Sites” scopes.

![][image21]

+-----------------------------------------------------------------------------------+
| Columns (contained, fullscreen images)                                            |
+---------------------------------------------------------------+-------------------+
| After that, the registration portal should show `canRead: ok` | ![][image22]      |
+---------------------------------------------------------------+-------------------+

[image0]: https://main--helix-website--adobe.aem.page/media_1efffe0288d261803d829a5fbc7f0d34748e6dacc.png#width=1463&height=1097 "Adobe Logo"

[image1]: https://main--helix-website--adobe.aem.page/media_1a21e5630caea6df81f56b8e57c8f7397e7deae60.png#width=1600&height=865

[image2]: https://main--helix-website--adobe.aem.page/media_1a39f3177a20c4d3712d6c710c465021fa3267941.png#width=1600&height=356

[image3]: https://main--helix-website--adobe.aem.page/media_1b703af395a0ab1792f8541e52850261d58ef904b.png#width=1600&height=410

[image4]: https://main--helix-website--adobe.aem.page/media_1190bb8f4b278ac17607a9a0b6b6a850b9687273b.png#width=1600&height=1322

[image5]: https://main--helix-website--adobe.aem.page/media_16cab4000fae428c4c76f206cd38f7ac0f42b1da4.png#width=1600&height=1318

[image6]: https://main--helix-website--adobe.aem.page/media_1cf6de0cf406aa1ee075864db83ea8ae0ab0b6649.png#width=932&height=920

[image7]: https://main--helix-website--adobe.aem.page/media_12b65935a94412edf20d183e8191ce696e036a03f.png#width=932&height=920

[image8]: https://main--helix-website--adobe.aem.page/media_16b51d539119f1d70a06b077e56400387e91eabcb.png#width=1308&height=1032

[image9]: https://main--helix-website--adobe.aem.page/media_1c7f188ae128dafecf1aa05b89647ab65b22a9988.png#width=1308&height=1032

[image10]: https://main--helix-website--adobe.aem.page/media_18ff0191a2d962ebc439d12bd37759aac7e396883.png#width=803&height=902

[image11]: https://main--helix-website--adobe.aem.page/media_12ef43856b5964bd7f80caaf49932bec875fd31a7.png#width=1600&height=1322

[image12]: https://main--helix-website--adobe.aem.page/media_17d2726b0f7853fe8ae2562cd881d577ba9d8bcc6.png#width=1308&height=1032

[image13]: https://main--helix-website--adobe.aem.page/media_11983dd34d29c068da4ee50882a0f906535b7b93f.png#width=1373&height=1600

[image14]: https://main--helix-website--adobe.aem.page/media_187fe82f471856af1d141165fa46cf98b6dbf2ada.png#width=1600&height=1374

[image15]: https://main--helix-website--adobe.aem.page/media_1d8e68ed60aac9e095e8ce086d43d711da0c9061a.png#width=1300&height=1600

[image16]: https://main--helix-website--adobe.aem.page/media_1aae332e3995979a51198e863371a2116f712a62a.png#width=1363&height=1600

[image17]: https://main--helix-website--adobe.aem.page/media_1e08c17483309293e7e90f74c80c107807a3cc8bd.png#width=1311&height=1009

[image18]: https://main--helix-website--adobe.aem.page/media_1b02e614e714532854393c52bf3afab6ad860c3bf.png#width=1238&height=1061

[image19]: https://main--helix-website--adobe.aem.page/media_108467abcda4be68630054090a3368d6b3ac529a8.png#width=1355&height=1090

[image20]: https://main--helix-website--adobe.aem.page/media_1addeb7fe8c51b3fbb4293e05737e6ff788628f7d.png#width=1363&height=1600

[image21]: https://main--helix-website--adobe.aem.page/media_18d2eb4327ffc752f17827d833bd1301c3f9e2837.png#width=720&height=230

[image22]: https://main--helix-website--adobe.aem.page/media_14dfd407c3cdf6be44b304cbca47df3b0e7b37ae2.png#width=1600&height=1592
