We encode the Sharepoint application, extend it as a provider using a certificate, and bind our MVC project to it. Deploy it all on the same IIS that Sharepoint expanded.
Task No. 1: the user registers in Sharepoint, launches our application; the application starts without any authorization request and receives the user from a registered Sharepoint user.
Task No. 2: If you need a Sharepoint service request, our application is registered in Sharepoint under the same username that is registered in Sharepoint.
We tried:
1) . Create an application hosted on the hosting provider, creating our MVC in it, creating a self-singing certificate, setting up a highly reliable connection between the Sharepoint website and our MVC.
We got: If our MVC uses Windows authentication, then when transferring to our application, the username and password are again requested; when entering them, we can get the ClientContext through TokenHelper using the GetS2SClientContextWithWindowsIdentity method.
If Windows authentication is disabled, the user is not logged in to the request, and this method responds with the Exception that the user is not logged on.
2) We installed and configured ADFS, configured Sharepoint to work with ADFS, wrote the addresses of Sharepoint and our application in Relaying Party Trusts (in Identifiers and WS-Fedistry` passive endpoints)
We have received: The user is registered in Sharepoint, and when transferred to our application, the latter receives user data (claims)
Thus, the first task is completed. After that, there was a problem getting access to Sharepoint services under an authorized user.
We tried to get the AccessToken for Sharepoint through the claims we received. We tried to transfer the following claims:
nii":"trusted:adfs nii":"urn:office:idp:forms:adfs201 //adfs201 - name of our ADFS service upn:UserLogin emailaddress:UserEmail@domain.kz
After that, we called the method that responds with the AccessToken in accordance with the entered claims
string issuer = string.IsNullOrEmpty(sourceRealm) ? issuerApplication : string.Format("{0}@{1}", issuerApplication, sourceRealm); string nameid = string.IsNullOrEmpty(sourceRealm) ? sourceApplication : string.Format("{0}@{1}", sourceApplication, sourceRealm); string audience = string.Format("{0}/{1}@{2}", targetApplication, targetApplicationHostName, targetRealm); List<JsonWebTokenClaim> actorClaims = new List<JsonWebTokenClaim>(); actorClaims.Add(new JsonWebTokenClaim(JsonWebTokenConstants.ReservedClaims.NameIdentifier, nameid)); if (trustedForDelegation && !appOnly) { actorClaims.Add(new JsonWebTokenClaim(TokenHelper.TrustedForImpersonationClaimType, "true")); } if (addSamlClaim) actorClaims.Add(new JsonWebTokenClaim(samlClaimType, samlClaimValue)); // Create token JsonWebSecurityToken actorToken = new JsonWebSecurityToken( issuer: issuer, audience: audience, validFrom: DateTime.UtcNow, validTo: DateTime.UtcNow.AddMinutes(TokenLifetimeMinutes), signingCredentials: SigningCredentials, claims: actorClaims); string actorTokenString = new JsonWebSecurityTokenHandler().WriteTokenAsString(actorToken); if (appOnly) { // App-only token is the same as actor token for delegated case return actorTokenString; } List<JsonWebTokenClaim> outerClaims = null == claims ? new List<JsonWebTokenClaim>() : new List<JsonWebTokenClaim>(claims); outerClaims.Add(new JsonWebTokenClaim(ActorTokenClaimType, actorTokenString)); //**************************************************************************** //SPSAML if (addSamlClaim) outerClaims.Add(new JsonWebTokenClaim(samlClaimType, samlClaimValue)); //**************************************************************************** JsonWebSecurityToken jsonToken = new JsonWebSecurityToken( nameid, // outer token issuer should match actor token nameid audience, DateTime.UtcNow, DateTime.UtcNow.AddMinutes(10), outerClaims); string accessToken = new JsonWebSecurityTokenHandler().WriteTokenAsString(jsonToken);
Then we tried to get the ClientContext using the method:
GetClientContextWithAccessToken(targetApplicationUri.ToString(), accessToken);
But we got an error message:
401 Unauthorized
ClientID and IssureID were spelled correctly in lowercase
After that, we decided to request SecurityToken from ADFS using username and password . Having received it, we requested authorization in SharepointSTS using SecurityToken . Then our application received Sharepoint cookies, which were tied to the request (added to CookieContainer FedAuth ) to Sharepoint services. When you activate ExecutingWebRequest += ClientContext_ExecutingWebRequest , the above happens.
But for this you need to use the username and password tags again.
If we do not send username and password , then ADFS responds with a SecurityToken data of the user under whose name the application pool was launched. And we need a SecurityToken user registered in SharePoint . We also tried to release a SecurityToken
var session = System.IdentityModel.Services.FederatedAuthentication.SessionAuthenticationModule.CreateSessionSecurityToken(ClientPrincipals, "context", DateTime.UtcNow, System.DateTime.UtcNow.AddHours(1), true); System.IdentityModel.Services.FederatedAuthentication.SessionAuthenticationModule.AuthenticateSessionSecurityToken(session, true);
But the answer was not the same as we needed for SharePoint authorization.
In ADFS at the endpoints, we adjust the URL; which is very SecurityToken (wresult) we need SharePoint authorization to be sent to him at the request of POST. The problem is that we cannot receive this request in the application, because it is broadcast in state 302 and redirected to our application using the GET method, without SecurityToken with our Cookie.
Question: how can we get a SecurityToken user registered in SharePoint?