how Iis USES saml2.0 to access adfs - iis

How does IIS use saml2.0 to access adfs?
In my opinion, IIS needs to deploy a web application to access adfs by sending the request with saml 2.0.
But until now, I haven't found the way to deploy a web application that can send saml2.0.
Does it have to use isapi or Shibboleth ?
Resolution: (1) Shibboleth SP should establish the SSO session/HTTP
login session after extracting the user info from SAML response sent
by SAML IdP. (2) Insert the user info into the SSO session/HTTP login
session. How to insert and fetch Data from Sessions instead of
Database in Asp.net MVC C# provides the instruction on how to insert
data into the HTTP session (at IIS) and extract data from the HTTP
session (at Glassfish).
//In IIS Session["HTTP_MAIL"] = Request.Headers["HTTP_MAIL"];
//In Glassfish after HTTP redirect string user_email =
Session["HTTP_MAIL"];
Thanks for you answer!
let me tell about what I know first. If there is any something wrong, please point it out
Shibboleth SP save the value belongs of SAML response which is getting from SAML Idp(this time is ADFS) to three places(※), and we can see it in
https://SP's domaim name/Shibboleth.sso/Session
 ※
①Session
②Server Variables
③Request Headers
refer to SP's AttributeAccess
After Shibboleth SP save the value, automatically jumps to the interface accessed in the browser.
There is information in ②Server Variables and ③Request Headers, so applications above IIS can get it through the following code
through by both mail and HTTP_MAIL can get the value.
<% # Page Language="C#" %>
<%
Response.Write("<h3>Server Variables</h3>");
Response.Write("Name = " + Request["name"] + "<br>");
Response.Write("Email = " + Request["mail"] + "<br>");
Response.Write("Tel = " + Request["tel"] + "<br>");
%>
the result is :
Server Variables
Name = tom
Email = tom#yahoo.com
Tel = 0251-4584-635
the question is when use HTTP Redirect(HTTP Rewrite and other way is also ok),
How are the above values passed to glassfish~
Refer to your answer, I did the following things ~
Modify the program above iis to this:
<% # Page Language="C#" %>
<%
Response.Write("<h3>Server Variables</h3>");
Response.Write("Name = " + Request["name"] + "<br>");
Response.Write("Email = " + Request["mail"] + "<br>");
Response.Write("Tel = " + Request["tel"] + "<br>");
Session["HTTP_MAIL"] = Request["HTTP_MAIL"]; ※set value to Session
Response.Write("Mail2 = " + Session["HTTP_TEST"] + "<br>");
%>
create Glassfish's app to this:
#RequestMapping(value = "/info2", method = RequestMethod.GET)
public Object getUserInfo2(HttpSession session, Model model) {
Enumeration<String> headerNames = session.getAttributeNames();
StringBuffer stringBuffer = new StringBuffer();
while (headerNames.hasMoreElements()) {
String key = (String) headerNames.nextElement();
String value = (String) session.getAttribute(key);
stringBuffer.append(key + ":" + value + "\n");
}
model.addAttribute("StringBuffer", stringBuffer);
return "index";
}
there is nothing in session.
it seems that using IIS's HTTP redirect function to redirect the app on IIS before it executes.
In other words, the session assignment does not appear to have been performed
Did I do that right?

Question #1:
How does IIS use saml2.0 to access adfs?
In my opinion, IIS needs to deploy a web application to access adfs by sending the request with saml 2.0.
Answer:
Yes. You are correct.
(1) IIS needs to deploy a SAML SP (service provider) to send SAML auth request to ADFS.
(2) You need to configure ADFS to be SAML IdP (Identity Provider).
The official Microsoft website of Add ADFS as a SAML identity provider provides the instruction on how to configure ADFS to be SAML IdP.
Question #2:
Does it have to use isapi or Shibboleth ?
Answer:
You can deploy Shibboleth SP (service provider) on IIS.
The official link of Shibboleth SP with IIS provides the instruction on how to deploy Shibboleth SP on IIS.
Follow-up Question #1:
The final effect is as follows: adfs's end point:
iis.*.com/Shibboleth.sso/SAML2/POST
iis.*.com/Shibboleth.sso/SAML2/Artifact
However, adfs is returned as a post, and I did not get the information in the request header through the program on the iis side
Refer to this website Shibboleth SP for IIS でSAML対応
How can I get the data returned by adfs through get
Answer:
(1) Shibboleth SP AssertionConsumerService does NOT provide "HTTP-Redirect" endpoint/URL for "GET".
(I) You can NOT "get the data returned by adfs through get".
(II) You have to get the data returned by adfs through POST.
(2) Assume that your website is https://shibbolethiis.int.secioss.work
(I) Shibboleth SP AssertionConsumerService endpoint/URL demonstrated by your Shibboleth SP metadata "https://shibbolethiis.int.secioss.work/Shibboleth.sso/Metadata"
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://shibbolethiis.int.secioss.work/Shibboleth.sso/SAML2/POST" index="1"/>
(II) Quote the link from your comment. i.e., Shibboleth SP for IIS でSAML対応
「Default Web Site」を選択し。IISを再起動します。
これでShibboleth-SPの設定は終了です。
以下のURLに接続し、正常に稼働しているか確認してください。
https://shibbolethiis.int.secioss.work/Shibboleth.sso/Status
正常に稼働している場合、以下のようなXMLが返ります。
最後のStatusタグの内容がOKなら正常です。
(III) Check your website Shibbolth SP session
https://shibbolethiis.int.secioss.work/Shibboleth.sso/Session
The above Shibboleth SP Session URL should display the user info carried by SAML response sent by ADFS
If you can NOT find any user info from the above Shibboleth SP Session URL
(III.a) Configure ADFS to send the user info with SAML attribute/SAML assertion/SAML response
(III.b) Modify Shibboleth SP "attribute-map.xml" to accept SAML attributes sent by ADFS with reference to the example provided by Shibboleth SP shibboleth-sp-testapp/shibboleth-sp/attribute-map.xml at the GitHub repository.
Usually Shibboleth SP uses SAML attribute such as "mail" attribute (e.g., ethan.smith#example.com) to log the user in to your website.
(4) Remarks:
(I) How to build and run Shibboleth SAML IdP and SP using Docker container at GitHub repository provides Shibboleth SP configuration example.
(II) For your convenience, I have made a new commit to add ADFS attributes to Shibboleth SP shibboleth-sp-testapp/shibboleth-sp/attribute-map.xml at the above GitHub repository. Note that I have used the same ADFS attributes to log in to Box account successfully.
(III) Configuring Attributes for SAML 2.0 and ADFS 3.0 provides the valuable information and discussion on how Shibboleth SP extract the user info/data returned by ADFS through "attribute-map.xml".
Follow-up Question #2:
After modifying attribute. XML, and visit shibboleth.sso/Session, it can display the following information.
Attributes mail: 1 value(s)
tel: 1 value(s)
Refer to this website Shibboleth SP for IIS でSAML対応
5.動作確認
Display the following information
HTTP_MAIL:ya*#cn.*.com
HTTP_TEL:17*
how can i get information from the request header when i redirect it to glassfish via iis's HTTP redirect function?
Answer:
Another StackOverflow question Getting a Request.Headers value provides the solution on how to get information from the request header using C#, for example,
if (Request.Headers["HTTP_MAIL"] != null) {
string user_email = Request.Headers["HTTP_MAIL"];
}
Follow-up Question #3:
Instead of asking how to get headers on IIS, my question is how to get login information on glassfish~ In other words, how do i pass the request-header information to glassfish after getting it from iis? I also asked a question in glassfish get shibboleth sp attribute on iis, and it is more detailed than his current comment.
Answer:
From the cybersecurity perspective, you can NOT redirect the user info to establish the HTTP login session for Glassfish application. Otherwise, hackers can use the same user info to log in to Glassfish application without any authentication such as local username/password authentication or third-party SAML authentication.
Follow-up Question #4:
when use HTTP Redirect(HTTP Rewrite and other way is also ok), How are the above values passed to glassfish?
there is nothing in session.
it seems that using IIS's HTTP redirect function to redirect the app on IIS before it executes. In other words, the session assignment does not appear to have been performed
Did I do that right?
Answer:
(1) Apache, GlassFish, IIS, Jetty, and Tomcat can be regarded as parallel web servers for hosting web applications.
Top Java Application Servers: Tomcat vs. Jetty vs. GlassFish vs. WildFly
Microsoft IIS vs Apache Tomcat: What are the differences?
Microsoft IIS and Apache Tomcat belong to "Web Servers" category of the tech stack.
Windows Server 2016 can run both IIS 10 web server and GlassFish 5.1.0 web server, while IIS 10 web server and GlassFish 5.1.0 web server can run their own web application.
(2) From the cybersecurity perspective, different web application should establish their HTTP login session on their backend server (such as Apache, Glassfish, IIS, JETTY, and Tomcat) after their user has been authenticated by a third-party SAML IdP (such as Shibboleth SAML IdP).
Therefore, you can NOT redirect the user info from IIS to Glassfish, because IIS and Glassfish should establish their own different HTTP sessions for their user who is granted access to web application.
Resolution:
You can use OneLogin Java SAML SP tookit (Code Your Java App to Provide SSO via OneLogin) to build SAML SP for your Java-based GlassFish web application.
Note that OneLogin SAML SP for your Java-based GlassFish web application can communicate with any SAML IdP including their own OneLogin SAML IdP, Shibboleth SAML IdP running on Docker container, or SAML IdP provided by our Zero-Password Authentication and Authorization System.

Related

Shibboleth Proxy to Azure AD Validation Error on redirect with error XML element 'RequesterID' in XML namespace 'urn:oasis:names:tc:SAML:2.0:protocol'

I configured my local shibboleth IdP to proxy authentication to Azure AD but on redirect and getting an Azure error:
AADSTS7500522: XML element 'RequesterID' in XML namespace 'urn:oasis:names:tc:SAML:2.0:protocol' in the SAML message must be a URI.
My service provider that is redirecting to Shibboleth > AzureAD uses an entity ID that is just a name and not a URL which is what shows up in my saml trace back to Azure.
<saml2p:Scoping>
<saml2p:RequesterID>EntityIDShortName</saml2p:RequesterID>
</saml2p:Scoping>
Is there a way to turn off this validation in Azure or transform / not include the requester id from shibboleth to Azure AD?
I used this document to do the configuration:
https://shibboleth.atlassian.net/wiki/spaces/KB/pages/1467056889/Using+SAML+Proxying+in+the+Shibboleth+IdP+to+connect+with+Azure+AD
Thanks
Nick
FYI, just changing the entity I’d in my test provider addresses this issue.

Cannot Logout from IdentityServer 4 through Azure SAML logout request

Context
I have a Service Provider (SP) based on IdentityServer 4 and Sustainsys.Saml2.AspNetCore2 that is configured to use Azure as an IdP (SAML2).
I also have a SPA with an api that connects to my SP (with oidp) to identify my user. The api then creates a JWT for my user to use.
I can login my user correctly.
Question
My issue comes with the logout. I want to use the logout url parameter of Azure to notify my SP about the logout. I manage to see the SAML Logout Request as a string when I configure an endpoint of mine but I can't exploit it and parsing it manually does't seem right.
Is there an existing endpoint that would come with my dependencies that I missed?
The goal here is to revoke all my user's application sessions (the apps to which my user is connected throug my SP).
Configuration
Idp configuration in the SP (called in Startup.cs).
The Saml2AuthModel comes from a config file.
public static AuthenticationBuilder AddSaml2Auth(this AuthenticationBuilder builder, Saml2AuthModel saml2AuthModel)
{
builder.AddSaml2(saml2AuthModel.Scheme, saml2AuthModel.DisplayName ?? saml2AuthModel.Scheme, options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.SPOptions.EntityId = new EntityId(saml2AuthModel.ServiceProviderEntityId);
options.SPOptions.ModulePath = "/" + saml2AuthModel.ModulePath ?? saml2AuthModel.Scheme ?? options.SPOptions.ModulePath;
var idp = new IdentityProvider(
new EntityId(saml2AuthModel.IdentityProviderEntityId),
options.SPOptions
);
idp.MetadataLocation = saml2AuthModel.IdentityProviderMetadataLocation;
options.IdentityProviders.Add(idp);
});
return builder;
}
The Sustainsys.Saml2 library has support for single logout. To enable it, you need to set up a service signing key. The reason is that logout requests and responses should be signed. So the library doesn't expose the logout endpoints if it has no signing keys available.

Identity server 4 with SAML 2.0 as external identity provider for SSO

I am using identity server 4 for authentication to my ASP.Net Core solution. And it is working well with Facebook, Google and other external identity provider.
And now I am trying to add SAML 2.0 authentication to the identity server using Sustainsys.Saml2 from https://github.com/Sustainsys/Saml2 and making it work as an external identity provider. (Customers to our site want to login using their SAML identity provider using our Identity Server in the same way they can login via Facebook, Google, etc)
And what I have now is the
sign in URL - https://sso.domain.com/saml/idp/profile/redirectorpost/sso
sign out URL - https://sso.domain.com/saml/idp/profile/post/sls
CRT certificate
for the SAML based identity provider of our customer.
However, I cannot find the document that describes how to setup the configuration of SAML 2.0 in identity server 4 startup.cs file.
I think the configuration should look like the following based on the sample available at:
https://github.com/Sustainsys/Saml2/blob/master/Samples/SampleAspNetCore2ApplicationNETFramework/Startup.cs
services.AddAuthentication()
.AddSaml2(options =>
{
options.SPOptions.EntityId = new EntityId("...");
options.IdentityProviders.Add(
new IdentityProvider(
new EntityId("..."), options.SPOptions)
{
LoadMetadata = true,
});
options.SPOptions.ServiceCertificates.Add(new X509Certificate2("..."));
}
);
In the sample there are two url's
https://localhost:44342/Saml2
http://localhost:52071/Metadata
What do these represent?
Can somebody tell me how to setup all the options for SAML2 in identity server 4?
is the entity id of your application - corresponding to client id in open id connect.
is the entity id of the upstream idp.
There is a sample IdSrv4 in another branch: https://github.com/Sustainsys/Saml2/tree/netstandard/Samples/SampleIdentityServer4
The sample uses the preview version for .NET Core, but the config is basically the same.
There are working IdentityServer4 samples in https://github.com/Sustainsys/Saml2/tree/master/Samples

Authenticating Sharepoint 2013 on-premise with Azure AD

Our client has an Azure AD containing all users in his company located in multiple locations around the world. He would like his users to be able to sign into our SP app using their Microsoft Accounts which are on Azure AD.
Obviously, since Azure AD uses SAML 2.0, and SharePoint uses Ws-Fed (which is similar to SAML 1.1), we need to convert these claims from 2.0 to Ws-Fed (or SAML 1.1).
This used to be done using Azure's Azure Control Services, which is going to be deprecated at the end of the year (2018), so there's no point in developing a solution that uses it.
As such, we found a number of guides here and here which detail how a Claims Provider Trust can be created between Azure AD and ADFS, and a Relying Party Trust be set up between AD FS and SharePoint.
In theory this works in the following way:
User logs into his Microsoft Account which is on the Azure AD, and the SAML 2.0 token with claims is sent from Azure AD to AD FS
All claims are passed to AD FS, since we configured our rules in this way (as instructed here)
AD FS converts these from SAML 2.0 to Ws-Fed (or SAML 1.1)
AD FS maps the necessary claims to the UPN (as instructed here) and sends the result to SharePoint
We seem to be encountering an issue in the conversion step.
We have debugged the process using Fiddler, to see requests to and from the AD FS server. Azure AD claims are successfully sent to AD FS, but an error is encountered when AD FS is issue new claims (supposedly in Ws-Fed or SAML 1.1).
The following is the stack trace from AD FS:
Microsoft.IdentityServer.Web.RequestFailedException: MSIS7012: An error occurred while processing the request. Contact your administrator for details. ---> System.ServiceModel.FaultException: MSIS3127: The specified request failed.
at Microsoft.IdentityServer.Protocols.WSTrust.WSTrustClientManager.Issue(Message request, WCFResponseData responseData)
at Microsoft.IdentityServer.Protocols.WSTrust.WSTrustClient.Issue(RequestSecurityToken rst, WCFResponseData responseData)
at Microsoft.IdentityServer.Web.FederationPassiveAuthentication.SubmitRequest(MSISRequestSecurityToken request)
--- End of inner exception stack trace ---
at Microsoft.IdentityServer.Web.FederationPassiveAuthentication.SubmitRequest(MSISRequestSecurityToken request)
at Microsoft.IdentityServer.Web.FederationPassiveAuthentication.RequestBearerToken(MSISSignInRequestMessage signInRequest, SecurityTokenElement onBehalfOf, SecurityToken primaryAuthToken, String desiredTokenType, UInt32 lifetime, Uri& replyTo)
at Microsoft.IdentityServer.Web.FederationPassiveAuthentication.RequestBearerToken(MSISSignInRequestMessage signInRequest, SecurityTokenElement onBehalfOf, SecurityToken primaryAuthToken, String desiredTokenType, MSISSession& session)
at Microsoft.IdentityServer.Web.FederationPassiveAuthentication.BuildSignInResponseCoreWithSerializedToken(String signOnToken, WSFederationMessage incomingMessage)
at Microsoft.IdentityServer.Web.FederationPassiveAuthentication.BuildSignInResponseForProtocolResponse(FederationPassiveContext federationPassiveContext)
at Microsoft.IdentityServer.Web.FederationPassiveAuthentication.BuildSignInResponse(FederationPassiveContext federationPassiveContext, SecurityToken securityToken)
System.ServiceModel.FaultException: MSIS3127: The specified request failed.
at Microsoft.IdentityServer.Protocols.WSTrust.WSTrustClientManager.Issue(Message request, WCFResponseData responseData)
at Microsoft.IdentityServer.Protocols.WSTrust.WSTrustClient.Issue(RequestSecurityToken rst, WCFResponseData responseData)
at Microsoft.IdentityServer.Web.FederationPassiveAuthentication.SubmitRequest(MSISRequestSecurityToken request)
We've also done internal testing, whereby we logged in to the SharePoint site using the the local AD, in order to make sure that the setup between AD FS and SharePoint is correct. This worked as expected, and SharePoint received the claims as configured in step 4.
Any help with the "conversion" process from SAML 2.0 to Ws-Fed (or SAML 1.1) would be greatly appreciated.
Help me Obi-Wan Kenobi, you're my only hope!
Set AD FS' PreventTokenReplays param to false
In our case, this is what had us stuck for days. There was no mention of this anywhere that we read, and we only found out about it after going to the AD FS server's event viewer and going through the logs.
Open up PowerShell, and add the AD FS snapin using the following:
Add-PSSnapin Microsoft.Adfs.PowerShell
Then, get your AD FS properties, using the following:
Get-adfsproperties
Check the value for the PreventTokenReplays param. If it's set to false, you should be good.  If it's set to true, then flip it to false using the following command:
Set-adfsproperties -PreventTokenReplays $false
Now, you'll need to restart your AD FS service. Just go to services.msc, find AD FS 2.0 Windows Service, right click it, and hit restart.
Configuration Overview
Create a new Azure AD tenant and namespace.
Add a WS-Federation identity provider.
Add SharePoint as a relying party application.
Create a rule group for claims-based authentication.
Configure the X.509 certificate.
Create a claim mapping.
Configure SharePoint for the new identity provider.
Set the permissions.
Verify the new provider
You can follow this blog for step by step process
https://www.sharepointcollabs.com/2017/03/using-microsoft-azure-active-directory.html

Unable to authenticate to ASP.NET Web Api service with HttpClient

I have an ASP.NET Web API service that runs on a web server with Windows Authentication enabled.
I have a client site built on MVC4 that runs in a different site on the same web server that uses the HttpClient to pull data from the service. This client site runs with identity impersonation enabled and also uses windows authentication.
The web server is Windows Server 2008 R2 with IIS 7.5.
The challenge I am having is getting the HttpClient to pass the current windows user as part of its authentication process. I have configured the HttpClient in this manner:
var clientHandler = new HttpClientHandler();
clientHandler.UseDefaultCredentials = true;
clientHandler.PreAuthenticate = true;
clientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
var httpClient = new HttpClient(clientHandler);
My understanding is that running the site with identity impersonation enabled and then building the client in this manner should result in the client authenticating to the service using the impersonated identity of the currently logged in user.
This is not happening. In fact, the client doesn't seem to be authenticating at all.
The service is configured to use windows authentication and this seems to work perfectly. I can go to http://server/api/shippers in my web browser and be prompted for windows authentication, once entered I receive the data requested.
In the IIS logs I see the API requests being received with no authentication and receiving a 401 challenge response.
Documentation on this one seems to be sparse.
I need some insight into what could be wrong or another way to use windows authentication with this application.
Thank You,
Craig
I have investigated the source code of HttpClientHandler (the latest version I was able to get my hands on) and this is what can be found in SendAsync method:
// BeginGetResponse/BeginGetRequestStream have a lot of setup work to do before becoming async
// (proxy, dns, connection pooling, etc). Run these on a separate thread.
// Do not provide a cancellation token; if this helper task could be canceled before starting then
// nobody would complete the tcs.
Task.Factory.StartNew(startRequest, state);
Now if you check within your code the value of SecurityContext.IsWindowsIdentityFlowSuppressed() you will most probably get true. In result the StartRequest method is executed in new thread with the credentials of the asp.net process (not the credentials of the impersonated user).
There are two possible ways out of this. If you have access to yours server aspnet_config.config, you should set following settings (setting those in web.config seems to have no effect):
<legacyImpersonationPolicy enabled="false"/>
<alwaysFlowImpersonationPolicy enabled="true"/>
If you can't change the aspnet_config.config you will have to create your own HttpClientHandler to support this scenario.
UPDATE REGARDING THE USAGE OF FQDN
The issue you have hit here is a feature in Windows that is designed to protect against "reflection attacks". To work around this you need to whitelist the domain you are trying to access on the machine that is trying to access the server. Follow below steps:
Go to Start --> Run --> regedit
Locate HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0 registry key.
Right-click on it, choose New and then Multi-String Value.
Type BackConnectionHostNames (ENTER).
Right-click just created value and choose Modify.
Put the host name(s) for the site(s) that are on the local computer in the value box and click OK (each host name/FQDN needs to be on it's own line, no wildcards, the name must be exact match).
Save everything and restart the machine
You can read full KB article regarding the issue here.
I was also having this same problem. Thanks to the research done by #tpeczek, I developed the following solution: instead of using the HttpClient (which creates threads and sends requests async,) I used the WebClient class which issues requests on the same thread. Doing so enables me to pass on the user's identity to WebAPI from another ASP.NET application.
The obvious downside is that this will not work async.
var wi = (WindowsIdentity)HttpContext.User.Identity;
var wic = wi.Impersonate();
try
{
var data = JsonConvert.SerializeObject(new
{
Property1 = 1,
Property2 = "blah"
});
using (var client = new WebClient { UseDefaultCredentials = true })
{
client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
client.UploadData("http://url/api/controller", "POST", Encoding.UTF8.GetBytes(data));
}
}
catch (Exception exc)
{
// handle exception
}
finally
{
wic.Undo();
}
Note: Requires NuGet package: Newtonsoft.Json, which is the same JSON serializer WebAPI uses.
The reason why this is not working is because you need double hop authentication.
The first hop is the web server, getting impersonation with Windows authentication to work there is no problem. But when using HttpClient or WebClient to authenticate you to another server, the web server needs to run on an account that has permission to do the necessary delegation.
See the following for more details:
http://blogs.technet.com/b/askds/archive/2008/06/13/understanding-kerberos-double-hop.aspx
Fix using the "setspn" command:
http://www.phishthis.com/2009/10/24/how-to-configure-ad-sql-and-iis-for-two-hop-kerberos-authentication-2/
(You will need sufficient access rights to perform these operations.)
Just consider what would happen if any server was allowed to forward your credentials as it pleases... To avoid this security issue, the domain controller needs to know which accounts are allowed to perform the delegation.
To impersonate the original (authenticated) user, use the following configuration in the Web.config file:
<authentication mode="Windows" />
<identity impersonate="true" />
With this configuration, ASP.NET always impersonates the authenticated user, and all resource access is performed using the authenticated user's security context.

Resources