Date and Month display

Monday, December 14, 2015

Create a Provider Hosted Apps in SharePoint 2013 Step by Step approach

Provider Hosted Application is very useful to re-use the existing .Net application with very minor changes and their hosting environment. The topology of the Provider Hosted Application is as follows.

The user calls the SharePoint server and the SharePoint portal intern calls the .Net Application as a Separate Application. Moreover, there is an option to create an App Part and loads the .Net Application inside the App Part which can be placed on the SharePoint Page


Create a Provider Hosted App (High-trust) for SharePoint
SharePoint 2013 introduced the SharePoint App model for developers. Out of the three app models, SharePoint Hosted, Auto Hosted and Provider Hosted I’m creating and explaining the step by step approach to develop a simple Provider Hosted (High-trust) app in this post. This is not an introduction to SharePoint App model but an introduction to Provider Hosted (PH) Apps.
Diagram below denote my dev environment. 
One VM for AD and DNS and the second VM hosts SharePoint 2013 and SQL 2012.

Configure an environment for apps for SharePoint (SharePoint 2013)How to Configure DNS for App Development Model in SharePoint 2013: 

Please follow the tech net Microsoft link.


https://technet.microsoft.com/en-us/library/fp161236.aspx

There are two types of PH Apps. Apps that can be hosted in Office 365 environments and the PH Apps that can be only hosted in On-Premises environments which are also called as High-trust apps.
Provider Hosted app consists of an App deployed in to SharePoint and a separately deployed web application. In a production environment the web application is normally deployed in a separate server or a separate server farm.
The reason why high-trust apps are only compatible with On-Premises environments is, it uses a certificate instead of a context token (OAuth) to make the trust between the two servers. So these apps require some sort of configuration on the SharePoint server as well as the remote server hosting the web application. SharePoint includes server-to-server security token service (STS) which provides access tokens for server-to-server authentication. The server-to-server STS enables temporary access tokens to access other application services including apps for SharePoint 2013. To establish a trust relationship between the SP Server and App we use a X.509 certificate and a few PowerShell cmdlets.
We need to create a .pfx file and a corresponding .cer file. First file which is the pfx, contains the private key which will be used by the remote web application to encrypt it’s communication to SharePoint server. The .cer file contains the public key which will be used by SharePoint server to decrypt the messages and to verify those messages come from the same remote web application. Also to verify that the remote web application has an access token from a token issuer that SharePoint trusts which in this case the certificate.
For the demonstration purposes I will use a self signed certificate instead of a certificate issued by a certificate authority.
Create and export a Test Certificate
Open IIS Manager in the SharePoint server and select server certificates.  

Click Create a self-signed certificate.


Name the certificate. Mine is SharePointProviderHostedApps. 









As the next step, right click the certificate created, export it to a folder providing a password. It will create a file with a pfx extension. 


If your dev environment is not similar to mine and if you have a separate server to host the remote web application, please move the pfx file to the same.

Create the .cer file
Go to IIS Manager and open Server Certificates.

On the details tab, click Copy to file, where it opens the certificate export wizard. Click next and move forward with the default option, “No, Do not export the private key”.
Click next with default options and save the certificate.

Now we are done with certification creation & exporting part. But we have to make sure STS application pool identity as well as SharePoint Web Application; application pool identity have read permission to the location of the .cer file.

Configure SharePoint 2013 Server to use the Certificate and trust the App hosted in Remote Server.

Create SharePoint trusted token ID (Issuer ID) for Provider hosted App
We know that provider hosted app’s logic executes outside of the SharePoint farm and hence SharePoint farm needs to be authenticated via issuer Id and following script will help you to generate the Issuer ID
#Validate the request sent by external server via public certificate
  Add-PSSnapin "Microsoft.SharePoint.PowerShell"
  $issuerID = "af8e95ec-39c4-4578-93a6-77222fea8256"
  $targetSiteUrl = "http://c2wk32cmrshpwas42:11108/sites/test/"
  $targetSite = Get-SPSite $targetSiteUrl
  $realm = Get-SPAuthenticationRealm -ServiceContext $targetSite
  $registeredIssuerName = $issuerID + '@' + $realm
  $publicCertificatePath = "D:\Certs\SharePointApp2TogetSqlData.cer"
  $publicCertificate = Get-PfxCertificate $publicCertificatePath
  Write-Host "Create Security token issuer"
  $secureTokenIssuer = New-SPTrustedSecurityTokenIssuer -Name $issuerID -RegisteredIssuerName $registeredIssuerName -Certificate $publicCertificate -IsTrustBroker
  $secureTokenIssuer | select *
  $secureTokenIssuer  | select * | Out-File -FilePath "D:\Certs\SecureTokenIssuer.txt"
  #Turn off the HTTPS requirement for OAuth during development
  $serviceConfig = Get-SPSecurityTokenServiceConfig
  $serviceConfig.AllowOAuthOverHttp = $true
  $serviceConfig.Update()
  Write-Host "All done..."

Issuer Id                            : af8e95ec-39c4-4578-93a6-77222fea8256

The user calls the SharePoint server and the SharePoint portal intern calls the .Net Application as a Separate Application.
We can move on to the creation of Basic Provider Hosted Application using Visual Studio 2012.
Steps to Create a Provider Hosted Application:
1. Open the Visual Studio 2012 as Administrator



2. Click New Project.
3. Select the Template App for SharePoint 2013.

4. On the Creation of the Solution, Visual Studio will ask for the Site Collection against which we are going to deploy our app. And on the same screen, we need to choose the type of hosting which we are planning. In our case, it is going to be Provider Hosted Application.
5. On the selection of Provider Hosted, Click Next. The below screen will be asking the Certificate.
6. The Certificate needs to be created on the SharePoint machine and pfx file needs to be exported and shared with the Visual Studio Machine. Creating a certificate on the SharePoint machine has been mentioned in above. As of now, I am assuming that, we have a certificate created and an Issuer ID has been associated with the certificate
7. Now, the Solution has been created. The basic solution is as follows:


8. Our solution will comprise of 2 projects

a. ProviderHostedAppsForSQLData [App Project]
b. ProviderHostedAppsForSQLDataWeb [AppWeb Project]
9. ProviderHostedAppsForSQLData Project– This is going to be deployed on the SharePoint.
10. ProviderHostedAppsForSQLDataWeb Project – This is going to be the .Net Web Application. This application can be hosted on any IIS.
11. Go to the Property of the ProviderHostedAppsForSQLDataWeb (AppWeb) project and make sure that the Target Framework is set to 4.5
12. Create the virtual directory will be helpful to host our AppWeb on the Local IIS, instead of using the IIS Express, let us host our application on the IIS itself



13. By clicking the “Create Virtual Directory” button on the Web Tab, virtual directory will be created on the local IIS. You can confirm this by going to inetmgr.
14. After the property configurations, we are ready with our Provider Hosted Application. Rebuild the solution to make sure everything is fine.
15. Go to the AppManifest.xml in the App project. AppManifest file will be looking like this.


16. Modify the Start Page attribute to point the IIS directly. Please refer the below figure.



17. Go to Permissions Tab. Add the corresponding scope and the permissions as per the requirement. In this demo, I am adding the web as full control. This will give the rights to do CRUD Operations over the list present with in my web.
By doing this, we are sure that our app is having the Full Control Permission through the Web Scope.

18. The AppManifest.xml will be like this.


xml version="1.0" encoding="utf-8" ?>
<App xmlns="http://schemas.microsoft.com/sharepoint/2012/app/manifest"
     Name="ProviderHostedAppsForSQLData"
     ProductID="{23eed756-8c12-42bc-9a6d-2733e204b5be}"
     Version="1.0.0.0SharePointMinVersion="15.0.0.0">
  <Properties>
    <Title>ProviderHostedAppsForSQLData</Title>
    <StartPage>http://c245wccmrs456yfwas74/ProviderHostedAppsForSQLDataWeb/Pages/Default.aspx?{StandardTokens}</StartPage>
  </Properties>
  <AppPrincipal>
    <RemoteWebApplication ClientId="*" />
 </AppPrincipal>
  <AppPermissionRequests>
    <AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web" Right="FullControl" />
  </AppPermissionRequests>
</App>

19. Now, we came to the final step of our provider hosted application creation. That is, we need to register our clientID with the SharePoint before deploying the app.
20. ClientID is nothing but a GUID. But the only special thing about the ClientID is, it should be small case. i.e., something like 24576c92-961f-442b-a866-e612222cad36
21. To generate the GUID, we can’t use the “Create GUID” option in the Visual Studio. Because that will generate the GUID with Upper Case too. But, it will not work for our scenario.
22. Hence, from our SharePoint site itself, go to the AppRegNew.aspx page. The page will present inside the layouts folder. The URL would be something like https://c2dk76edwas74:45108/sites/test/_layouts/15/Appregnew.aspx.

23. The page will look like 
24. By clicking the “Generate Button” of the App ID, ClientID can be generated.
25. Copy the GUID and we need to paste that in 2 places.
 a. Web.Config File – App Settings.


<appSettings>
    <add key="ClientId" value="5c3994bd-1e0a-4dd5-ad08-22a5e178a9f3" />
    <add key="ClientSigningCertificatePath" value="D:\Certs\SharePointProviderHostedApps.pfx" />
    <add key="ClientSigningCertificatePassword" value="Welcome123" />
    <add key="IssuerId" value="af8e95ec-39c4-4578-93a6-77222fea8256" />
  </appSettings>
b. AppManifest.xml – AppPrincipal

<AppPrincipal>
    <RemoteWebApplication ClientId="5c3994bd-1e0a-4dd5-ad08-22a5e178a9f3" />
</AppPrincipal>

26. After updating the ClientID, we can build and deploy the solution. Right click the solution and click Deploy.
27. You will get the following error. Don’t panic about the error. Still we haven’t completed our app development. Still there is one last thing we need to do after getting this error.



[The specified application identifier 5c3994bd-1e0a-4dd5-ad08-22a5e178a9f3 is invalid or does not ex
ist.]
28. To rectify this error, we need to register our ClientID on the SharePoint Farm. We can do this by using PowerShell on the SharePoint Farm.
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
$appDisplayName = "ProviderHostedAppsForSQLData"
$clientID = "5c3994bd-1e0a-4dd5-ad08-22a5e178a9f3"
$targetSiteUrl = "http://c245wccmrs456yfwas74:11108/sites/test/"
$targetSite = Get-SPSite $targetSiteUrl
$realm = Get-SPAuthenticationRealm -ServiceContext $targetSite
$fullAppPrincipalIdentifier = $clientID + '@' + $realm
Write-Host "Registering new app principal"
$registeredAppPrincipal = Register-SPAppPrincipal -NameIdentifier $fullAppPrincipalIdentifier -Site $targetSite.RootWeb -DisplayName $AppDisplayName
$registeredAppPrincipal | select * | Format-List
$registeredAppPrincipal | select * | Format-List | Out-File -FilePath "Output.txt"
Write-Host "Registration Completed" 


Sunday, November 15, 2015

Get all users permission across Web Application through Power shell script

&lt;#
******-----------------------------------------------------------------------******
Author          -&gt; Shiv Mangal Singh
Date            -&gt; 12th Nov - 2015
Description     -&gt; This will get all site collections &amp; no.of sub sites across Web Application.
Path of csv file-&gt;$path = "D:\Test\Shiv\ps\TeamSites_Users_Permision_Report_smstest1.csv"
Web Application Name --&gt; "https://sharepoint.contact.contoso.net"

#Call the function to Check all Users Access
GetUserAccessReport "https://sharepoint.contact.contoso.net" "D:\Test\Shiv\ps\TeamSites_Users_Permision_Report_smstest1.csv"
******-----------------------------------------------------------------------******
 #&gt;

Add-PSSnapin Microsoft.SharePoint.Powershell  -EV Err  -EA "SilentlyContinue"

Function GetUserAccessReport($WebAppURL, $FileUrl)
{
#Get All Site Collections of the WebApp
$SiteCollections = Get-SPSite -WebApplication $WebAppURL -Limit All

#Write CSV- TAB Separated File) Header
"URL `t Title `t PermissionType/Groups Name `t Permissions `t LoginName `t Email" | out-file $FileUrl

  #Loop through all site collections
   foreach($Site in $SiteCollections)
    {
    # Skip the Orpahn site using below condition
    if($Site.url -ne "https://sharepoint.contact.contoso.net/sites/hrsite")
    {
    write-host $site.url
         #Check Whether the Search User is a Site Collection Administrator
         foreach($SiteCollAdmin in $Site.RootWeb.SiteAdministrators)
         {
           "$($Site.RootWeb.Url) `t $($Site.RootWeb.Title)`t Site Collection Administrator `t Site Collection Administrator `t $($SiteCollAdmin.LoginName)`t $($SiteCollAdmin.Email)" | Out-File $FileUrl -Append
         }

          #Loop throuh all Sub Sites
       foreach($Web in $Site.AllWebs)
       {  
                     if($Web.HasUniqueRoleAssignments -eq $True)
              {
                      #Get all the users granted permissions to the list
                   foreach($WebRoleAssignment in $Web.RoleAssignments )
                       {
                         #Is it a User Account?
                                         if($WebRoleAssignment.Member.userlogin)
                                                {
                                                    #Get the Permissions assigned to user
                                                     $WebUserPermissions=@()
                                                     foreach ($RoleDefinition  in $WebRoleAssignment.RoleDefinitionBindings)
                                                        {
                                                          $WebUserPermissions += $RoleDefinition.Name +";"
                                                        }
                                                        #write-host "with these permissions: " $WebUserPermissions
                                                         #Send the Data to Log file
                                                          if($WebRoleAssignment.Member.Email.Length -gt 0)
                                                          {
                                                           "$($Web.Url) `t $($Web.Title)`t Direct Permission `t $($WebUserPermissions) `t $($WebRoleAssignment.Member.LoginName)`t $($WebRoleAssignment.Member.Email)" | Out-File $FileUrl -Append
                                                          }
                                                          else
                                                           {
                                                            "$($Web.Url) `t $($Web.Title)`t Direct Permission `t $($WebUserPermissions) `t $($WebRoleAssignment.Member.LoginName)" | Out-File $FileUrl -Append
                                                            }
                                                }
                                  #Its a SharePoint Group, So search inside the group and check if the user is member of that group
                                  else
                                         {
                                            foreach($user in $WebRoleAssignment.Member.users)
                                                {
                                                                               #Get the Group's Permissions on site
                                                                                  $WebGroupPermissions=@()
                                                                           foreach ($RoleDefinition  in $WebRoleAssignment.RoleDefinitionBindings)
                                                                                  {
                                                                                    $WebGroupPermissions += $RoleDefinition.Name +";"
                                                                                  }
                                                                                  #write-host "Group has these permissions: " $WebGroupPermissions
                                                                               
                                                                                  #Send the Data to Log file
                                                                                  if($user.Email.Length -gt 0)
                                                                                    {
                                                                                  "$($Web.Url) `t $($Web.Title)`t  $($WebRoleAssignment.Member.Name) `t $($WebGroupPermissions) `t $($user.LoginName)`t $($user.Email)" | Out-File $FileUrl -Append
                                                                                  }
                                                                                  else
                                                                                  {
                                                                                  "$($Web.Url) `t $($Web.Title)`t  $($WebRoleAssignment.Member.Name) `t                                                                                    $($WebGroupPermissions) `t $($user.LoginName)" | Out-File $FileUrl -Append
                                                                                  }
                                                }
                                         }
                         }
                           }
                           }
                   
                           
                     }
                               
              }
              }

#Call the function to Check all Users Access
GetUserAccessReport "https://sharepoint.contact.contoso.net" "D:\Test\Shiv\ps\TeamSites_Users_Permision_Report_smstest1.csv"