I'm trying to implement a SAML 2.0 authentication against Windows ADFS for a web application. So far I succeeded in authenticating and getting what I need from ADFS by manually configuring the Relying Party Trust and the assigned Claim Rules.
Now I want to provide federation metadata for my application to make it easier to set up the required stuff in ADFS. However I can't figure out how to pass the required Claim Rules in that metadata.
Here's what I have so far:
<?xml version="1.0"?>
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="dokuwiki-entity" validUntil="2015-03-24T20:30:16Z">
<SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" WantAssertionsSigned="true">
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
<AssertionConsumerService index="1" isDefault="true" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://perd.cosmo/dw-2014-01-13/doku.php?id=start"/>
<AttributeConsumingService index="1">
<ServiceName xml:lang="en">DokuWiki</ServiceName>
<RequestedAttribute isRequired="true" Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="E-Mail-Adresse" />
</AttributeConsumingService>
</SPSSODescriptor>
<Organization>
<OrganizationName xml:lang="en">DokuWiki</OrganizationName>
<OrganizationDisplayName xml:lang="en">DokuWiki</OrganizationDisplayName>
<OrganizationURL xml:lang="en">https://www.dokuwiki.org</OrganizationURL>
</Organization>
</EntityDescriptor>
From what I understand the RequestedAttribute should tell the ADFS to send me the user's E-Mail address upon authentication. Unfortunately after using this metadata to set up the Relying Party Trust no Claim Rules are set up.
Question: Is it possible to set up Claim Rules through metadata or has this always to be done manually? If it is possible where do I find the appropriate documentation?
You have to setup the claimsrules manually (or through powershell). ADFS does not look at that part of the metadata.
Related
Briefly
Should I be using OpenIdConnectDefaults.AuthenticationScheme when authenticating with Azure ADFS?
In more detail
I have an ASP.NET Core application that has recently been upgraded from 3.1 to .NET 5.
Previously, it had been using the following NuGet package:
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.1.9" />
and the following in my StartUp.cs:
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => this.Configuration.Bind("AzureAd", options));
Today, I updated the NuGet package:
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="5.0.3" />
And immediately received warnings that I was using deprecated/obsolete code.
I was directed to the Microsoft Identity Web page for more information....seemed like a lot to trawl through to find what I wanted.
I did read though that the Visual Studio Preview version had an updated Project Template, so I created a new project and this connected to Azure and I was logged in with my domain credentials. Fantastic!
The relevant NuGet packages it used appear to be:
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.3" NoWarn="NU1605" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.3" NoWarn="NU1605" /
<PackageReference Include="Microsoft.Identity.Web" Version="1.1.0" />
<PackageReference Include="Microsoft.Identity.Web.UI" Version="1.1.0" />
So, Authentication done. Now onto Authorization.....
So we have our own home-grown Authorization service. We send the user's identity (from ADFS) to this and it returns what they're allowed to do. This is where things broke....
Our original code for this used the "Upn" claim from the response from Azure ADFS:
Claim? upnClaim = identity.FindFirst(ClaimTypes.Upn);
This returns the claim with the email address.
However, this now returned null.
The following code did get the claim with the email address:
Claim? upnClaim = identity.FindFirst("preferred_username");
So, I could run with this and it would work.....
However, I would like to know if using OpenIdConnectDefaults.AuthenticationScheme is the preferred option for the latest Microsoft Identity and Azure ADFS? The fact that I'm having to use a magic string "preferred_username" rather than ClaimTypes.Upn gives me some doubt.
Does anyone have any deep insight into this?
The fact that I'm having to use a magic string "preferred_username" rather than ClaimTypes.Upn gives me some doubt.
preferred_username is not a magic string, it's documented as one of the claims that AAD adds to the id token payload, see https://learn.microsoft.com/azure/active-directory/develop/id-tokens#payload-claims.
The underlying library used by the ASP.NET Core OpenID Connect provider used to map claims to match well-known claims in the .NET world. Maybe Microsoft.Identity.Web disables that specific behaviour.
I blogged about this a while back at https://mderriey.com/2019/06/23/where-are-my-jwt-claims/.
We had built widgets for LinkedIn in Salesforce (Force.Com) Enterprise Version Environment using their API which has stopped working from some time. It is causing major Inconveniences for the affected users. Kindly share if similar issue has been noticed at your end and a fix for it.
Here are the steps we performed till date:
After achieving the successful authentication using Oauth 2.0,we are using “people search” for the LinkedIn search functionality.
Response we were getting , when we were making a GET request for the people search API:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<error>
<status>403</status>
<timestamp>1433254195523</timestamp>
<request-id>PY4LJUNDOX</request-id>
<error-code>0</error-code>
<message>Access to people search denied.</message>
</error>
Starting from May 12, 2015, Linkedin has limited the open APIs.
Access to Groups requires that you apply for and are granted access to this information from LinkedIn.
The following endpoints are available for general use:
Profile API — /v1/people/~
Share API — /v1/people/~/shares
Companies API — /v1/companies/{id}
If your application is currently using any other API services (e.g. Connections, Groups, People Search, Invitation, Job Search, etc.) you will have to apply to become a member of a relevant Partner Program that provides the necessary API access to continue to leverage any of the endpoints that are not listed above.
Check out this link for the list of API changes that were announced.
Http Form adapter serves as an authentication service in my application. I have not implemented any application on the Identity Provider to get user inputs.
Therefore, on successful authentication, SP verifies the user's signature and redirects to the application. At my target Resource, I receive an open token. Is it still possible to utilize the open Token Jar to read the user attributes from OTK?
**Note: ** In Service Provider, I use open token Adapter.
Also, please let me know if there is any other possible way of getting the user attributes other than using the open token adapter/http form adapter.
Thanks.
There are numerous SP Adapters you can choose to use for your last mile integration with your application. The OpenToken Adapter is just one of them. If your application is in Java and you are using the SP OpenToken Adapter, then you would most likely use the Java OpenToken Agent implementation within your application to read the OTK (documented in the Java Integration Kit). If you look at the Add Ons list, there are actually 3 flavors of OTK Agents (.NET, Java and PHP from PingID. Ruby on Rails and Perl are available via respective Open Source repositories).
However, you are not limited to OpenToken Adapters. The Agentless Integration Kit is also very popular for SP/last-mile integration with PingFederate.
Unfortunately, the question is just too open ended for the Stackoverflow format. I would suggest talking to your Ping Identity Solution Architect who can help steer you in the right direction and ask the necessary follow-up questions on your use case.
If understand the question correctly, you desire attributes to be fulfilled that the web application can read and utilize. This starts with the SP Connection configuration. I am going to assume you are using Active Directory and already configured that data source along with the Password Credential Validator (PCV) for the HTML Form IdP Adapter. In the SP Connection you will need to extend the attribute contract to define the values to put into the SAML assertion and then use the Active Directory data source to fulfill the attributes. When the SAML assertion is received by the PingFederate SP role server, the SP Adapter maps the attribute values from the SAML assertion into the OpenToken. When your application receives the OpenToken, it can read the values.
I've successfully implemented SSO authentication using Spring-SAML extension. Primary requirement for us to support IDP-initiated SSO to our application. Well, by using the configurations from spring-security-saml2-sample even SP-initiated SSO flow also works for us.
Question: Is keystore is used in IDP-initiated SSO (if metadata has certificate)? If not used, I would like to get rid of keystore configurations from securityContext.xml.
Note: SP-initiated SSO and Global logout is not needed for us. We use Okta as IDP.
This is a good feature request. I've opened https://jira.spring.io/browse/SES-160 for you and support is available in Spring SAML's trunk with the following documentation:
In case your application doesn't need to create digital signatures
and/or decrypt incoming messages, it is possible to use an empty
implementation of the keystore which doesn't require any JKS file
- org.springframework.security.saml.key.EmptyKeyManager. This can be the
case for example when using only IDP-Initialized single sign-on.
Please note that when using the EmptyKeyManager some of Spring SAML
features will be unavailable. This includes at least SP-initialized
Single Sign-on, Single Logout, usage of additional keys in
ExtendedMetadata and verification of metadata signatures. Use the
following bean in order to initialize the EmptyKeyManager:
<bean id="keyManager" class="org.springframework.security.saml.key.EmptyKeyManager"/>
I would like to configure Tomcat to be able to connect to AD and authenticate users accordingly.
In addition, I would also like to invoke some web services (in this case, Share Point) using the client credentials.
So far, I've managed to successfully configure Tomcat to use SPNEGO authentication, as described in the tutorial at http://tomcat.apache.org/tomcat-7.0-doc/windows-auth-howto.html. Note that I have used Tomcat's SPNEGO authentication (not Source Forge's or Waffle).
I did not use Source Forge's implementation since I wanted to keep things simple and use Tomcat's as provided out of the box. In addition, I wanted all the authentication and authorization to be handled by Tomcat, using the SPNEGO as the authentication method in WEB.XML and Tomcat's JNDI realm for authorization.
Also I have not used WAFFLE, since this is Windows only.
I'm using CXF as my Web Service stack. According to the CXF documentation at http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html#ClientHTTPTransport%28includingSSLsupport%29-SpnegoAuthentication%28Kerberos%29, all you need to do to authenticate with the a web service (in my case, Share Point) is to use:
<conduit name="{http://example.com/}HelloWorldServicePort.http-conduit"
xmlns="http://cxf.apache.org/transports/http/configuration">
<authorization>
<AuthorizationType>Negotiate</AuthorizationType>
<Authorization>CXFClient</Authorization>
</authorization>
</conduit>
and configure CXFClient in jaas.conf (in my case, where Tomcat's server JAAS configuration is located, such that my jass.conf looks like:
CXFClient {
com.sun.security.auth.module.Krb5LoginModule required client=true useTicketCache=true debug=true;
};
com.sun.security.jgss.krb5.initiate {
com.sun.security.auth.module.Krb5LoginModule required
doNotPrompt=true
principal="HTTP/tomcatsrv.corporate.intra#CORPORATE.INTRA"
useKeyTab=true
keyTab="C:/Program Files/Apache/apache-tomcat-7.0.27/conf/tomcatsrv.keytab"
storeKey=true
debug=true;
};
com.sun.security.jgss.krb5.accept {
com.sun.security.auth.module.Krb5LoginModule required
doNotPrompt=true
principal="HTTP/tomcatsrv.corporate.intra#CORPORATE.INTRA"
useKeyTab=true
keyTab="C:/Program Files/Apache/apache-tomcat-7.0.27/conf/tomcatsrv.keytab"
storeKey=true
debug=true;
};
Yet, when I'm invoking the web service, it is invoked under the service username (i.e. Tomcat's username configured in AD and in tomcatsrv.keytab), rather than the client's username (e.g. duncan.attard).
So my question is this: Is there some way in which the client's username can be delegated (or use some sort of impersonation) to CXF so that when I invoke Share Point's web service (e.g. I want to upload a file using Copy.asmx), the file is uploaded as duncan.attard and not as tomcat.srv.
Thanks all, your help is much appreciated.
Technically, this works perfectly. Here's the recipe:
You do not need a login module name if you work with credential delegation.
You have to make sure that the user account is eligible for delegation.
Take a look at the implementation of Tomcat's GenericPrincipal, it will save you the GSS credential if there is one. Cast request.getPrincipal to GenericPrincipal and get the credential.
Now say you have the credential:
Construct a Subject with the Principal and the GSSCredential as private credential.
Wrap the CXF code into a PrivilegedAction.
Pass the constructed subject and an instance of your privileged action to the Subject.doAs method and the system will construct an AccessControlContext on behalf of the passed subject and will invoke everything in JAAS on behalf of that context. CXF should use those if it is implemented correctly. This is like su or sudo on Unix.
The easiest way to test that is to create an InitialDirContext in the privileged action on behalf of the client to your Active Directory. This is how I test a working credential delegation environment.