SharePoint Authentication How to get a SharePoint cookie from ADFS

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?

+8
c # asp.net-mvc sharepoint
source share
1 answer

Go on a whim here, but it looks like you need to create a claims provider, which is a class that inherits from SPClaimProvider.

The people collector at sharepoint, which is the control you use to select people and groups, gets all this from people and groups from claim providers.

The following Requirement Providers are available out of the box,

AllUsersClaimProvider FormsClaimsProvider ActiveDirectoryClaimsProvider

If you require additional resolution of claims, you need to write one thing, which is not so bad.

http://msdn.microsoft.com/en-us/library/office/ee537299(v=office.15).aspx

Basically, FillClaimsForEntity is where you can make new claims to the Identity Principle.

The two Resolve Overloads parameters are where you see if there is a match for the input.

eg. let's say you type “bob” in the people picker. The people collector then uses SPClaimsOperationManager * (forget the exact spelling) to call Resolve (string input ...) for each claims provider registered in the farm.

So, we say that we are talking about the supplier of applications for forms. He will check to see if there is a user with a username or email address matching Bob. For each user matching bob, he will create a picker and set the application type to FormsLogonUser with bob, etc. And he adds every result.

So when you do this, you will either see Bob in the People Picker, or you will see that Bob with a red underline means that they were multiple matches, and you need to choose.

It seems to me that you need to create one to allow the people picker to work with your new requirements.

Once you have created and registered a claim provider, you can use the People Picker to provide access to the site using your requirements.

For an exemplary scenario, I once made a requirements provider that issued claims based on which products users bought.

So, I made the claim type “ http://blah.com/schema/claims/product ” (it could be any unique string you want) And the values ​​were things like “pd.1234.0”. Now in FillClaimsForEntities I searched for the user in the entity parameter in our database to get all their products. Then I created a product request for each product and added them to the claims list.

Then in Resolve, I would look to see if there is a product with an identifier or display name that defines the permission entry, and create a picker if it did.

Same thing in the search.

Then I went into our product pages and granted access to the page to anyone who has complaints about this product using the people builder. "works like gathering a role in form authentication."

You can also program support for Heirarchy Claims, and you can have several trees in the people picker, one tree for each claim type you are working with.

eg. let's say "Bob" returns the person, book, and manager. You can have 3 hierarchies, 1 for people, 1 for books, 1 for managers, etc. And make statements of this type appear in this tree.

I took a step further and made an access denial handler so that if a user got access, refusing that he was not in the declared product, he redirected them to this product purchase page.

0
source share

All Articles