I am working on integrating Spring SAML Extension within our appliaction and for SSO with one of our client's ADFS2.0 as the IDP we have generated Service provider meta data from our appliaction and imported ADFS meta data into our appliaction.When i select the clients idp and click on start single sign and give the proper clients credentials we are seeing the the SAML response as follows:
Saml Response.
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified"
Destination="https://sso.spire2grow.com:8443/<our application>/saml/SSO" ID="_d7fa7cb7-a858-4d4e-aa4c-bf7a5d11e485"
InResponseTo="a2icei36d347di68gi33534cc13fd1" IssueInstant="2014-09-30T14:17:21.819Z" Version="2.0"><Issuer
xmlns="urn:oasis:names:tc:SAML:2.0:assertion"><Clients ADFS trust services URL></Issuer><samlp:Status><samlp:StatusCode
Value="urn:oasis:names:tc:SAML:2.0:status:Responder"></samlp:StatusCode></samlp:Status></samlp:Response>
but also i am seeing following exception being thrown as the service provider is not able to validate the message.
Exception message:
[351545]2014-09-30 19:47:21,714 DEBUG - SAML message intended destination endpoint matched recipient endpoint
[351545]2014-09-30 19:47:21,714 DEBUG - Authentication attempt using org.springframework.security.saml.SAMLAuthenticationProvider
[351545]2014-09-30 19:47:21,715 DEBUG - Error validating SAML message
org.opensaml.common.SAMLException: Response has invalid status code urn:oasis:names:tc:SAML:2.0:status:Responder, status message is null
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:113)
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:82)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:84)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:195)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
Could any one please point out if i mising any thing here.
UPDATE:
After seeing the answer provided for this question
I saw the following error from ADFS.
Microsoft.IdentityServer.Protocols.Saml.SamlProtocolSignatureAlgorithmMismatchException: MSIS7093: The message is not signed with expected signature algorithm. Message is signed with signature algorithm http://www.w3.org/2000/09/xmldsig#rsa-sha1. Expected signature algorithm http://www.w3.org/2001/04/xmldsig-more#rsa-sha256. at Microsoft.IdentityServer.Web.Protocols.Saml.SamlProtocolManager.ValidateSignatureRequirements(SamlMessage samlMessage) at Microsoft.IdentityServer.Web.Protocols.Saml.SamlProtocolManager.Issue(HttpSamlRequestMessage httpSamlRequestMessage, SecurityTokenElement onBehalfOf, String sessionState, String relayState, String& newSamlSession, String& samlpAuthenticationProvider, Boolean isUrlTranslationNeeded, WrappedHttpListenerContext context, Boolean isKmsiRequested)
But after seeing this we did change the Signing algorithm on the relying trust party to rsa-sha256 but still its displaying the same message .
Do we need a genuine certificate for rsa-sha256? Will the self-signed certificate properly work?
The exception from ADFS complains that the SAML message was not signed with RSA-SHA256 which it expects, but with RSA-SHA1.
Make sure to set signing algorithm of the Spring SAML's Relaying Party in ADFS to SHA-1. You can find details in the last bullet point of http://docs.spring.io/autorepo/docs/spring-security-saml/1.0.x-SNAPSHOT/reference/htmlsingle/#chapter-idp-guide-adfs-sp
Value="urn:oasis:names:tc:SAML:2.0:status:Responder"
See SAML core specification. It says:
urn:oasis:names:tc:SAML:2.0:status:Responder
The request could not be performed due to an error on the part of the SAML
responder or SAML authority.
i.e. The ADFS server had trouble interpreting or answering the request. The IdP should tell you what the problem is.
Spring Security SAML extension does not support SHA-256 by defualt. You can extend the org.springframework.security.saml.SAMLBootstrap class to provide the SHA-256.
Override the postProcessBeanFactory method
public class Bootstrap extends SAMLBootstrap {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
super.postProcessBeanFactory(beanFactory);
BasicSecurityConfiguration config = (BasicSecurityConfiguration) Configuration
.getGlobalSecurityConfiguration();
config.registerSignatureAlgorithmURI("RSA", SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
}
Related
I may have the wrong idea of how I should go about these things, but this is currently the case:
I have a WebApi service that accepts requests from Sharepoint Online (SPO), which have SAML2 token passed within. The SAML2 token is issued by SPO STS, and I will need to validate the token, and extract claims out of it.
My question is how do I validate the token? Is there a way to trust the STS somehow, so I can just verify the signature (possibly will have to decrypt the token as well) all in-place? If not, and I have to make another call to STS, what should be the endpoint to validate the token? I couldn't find much documentation on this.
If you're using O365 as STS or IdP and that provides the SAML2.0 Assertion to your service, then you have to get its X509Certificate (to verify the signature of received SAML2.0 Assertion) from metadata link: https://login.microsoftonline.com/<TenantDomainName>/FederationMetadata/2007-06/FederationMetadata.xml.
Make sure you retrieve X509Certificate from EntityDescriptor-> IDPSSODescriptor-> KeyDescriptor use="signing" -> KeyInfo-> X509Data-> X509Certificate.
I'm trying to use the authenticationendpoint application that comes with WSO2 as the new only login entry point of an old application. For testing purposes I just did a page that redirects to thi URL
https://localhost:9443/authenticationendpoint/login.do?relyingParty=My-Issuer&sp=Test-App&sessionDataKey=14792551&authenticators=BasicAuthenticator:LOCAL
The login page appears as expected, but once I set the user and password shows this message:
Authentication Error !
Attention:
Something went wrong during the authentication process. Please try signing in again.
Seeing the output in the console on debug mode, this is what is shown
... Many of the same error saying that Authentication Context is null
[2017-01-06 15:40:08,836] DEBUG {org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils} - Authentication Context is null
[2017-01-06 15:40:08,836] DEBUG {org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils} - Authentication Context is null
[2017-01-06 15:40:08,836] DEBUG {org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils} - Authentication Context is null
[2017-01-06 15:40:08,837] DEBUG {org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultRequestCoordinator} - Session data key : 22451696
[2017-01-06 15:40:08,837] ERROR {org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultRequestCoordinator} - Context does not exist. Probably due to invalidated cache
I thing I'm doing something wrong, maybe there are not enough parameters sent, or they are the wrong ones, the user and password are correct because I can login into the carbon itself with it, and it is also a valid user for the testing SP.
The SP config is described:
Basic Information
Service Provider Name: Test-App
Claim configuration
Use Local Claim Dialect
Subject Claim URI http://wso2.org/claims/username
Role/Permission Configuration
Permissions AdminTest
Role Mapping AdminTest->Admin
Inbound Authentication Configuration
SAML2 Web SSO Configuration
Issuer: My-Issuer
Assertion Consumer URLs: https : //localhost/Test/main.asp
Default Assertion Consumer URL: https : //localhost/Test/main.asp
NameID format: urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
Certificate alias: wso2carbon
Response Signing Algorithm: ...#rsa-sha1
Response Digest Algorithm: ...#sha1
Checked values
Enable Response Signing
Enable Single Logout
Enable Attribute Profile
Include Attributes in the Response Always
Enable IdP Initiated SSO
Enable IdP Initiated SLO
Others are in blank OAuth, OpenID, etc (let me know if that is maybe the problem, so which should be filled out.
Local and Outbound Authentication Configuration
Authentication Type: I tried with Default and Local Authentication = basic and password-reset-enforcer
This is checked:
Assert identity using mapped local subject identifier
Use tenant domain in local subject identifier
Use user store domain in local subject identifier
Request Path Authentication Configuration
basic-auth
Inbound Provisioning Configuration
SCIM Configuration
PRIMARY
Dumb Mode is not enabled
The rest is left blank
I have spent many days tracking this problem but no answers or are for older versions.
I tested with JDK 7 and 8 (latest of them) I'm working with WSO2 IS 5.2.0. Someone can lead me to a solution to use this application as the only entry point for my SPs? The idea after is to send back a SAML2 response to a page in the SP side that read the information and control the authorization part.
Thanks in advance.
You have configured for a SAML SSO scenario. Therefore your SP have to call the SAML SSO endpoint of WSO2 Identity Server with a valid SAMLRequest. That is https://hostname:port/samlsso.
AuthenticationEndpoint is just an intermediary application. SAML SSO endpoint is the one that should redirect the user to AuthenticationEndpoint after first processing the SAMLRequest. You must not call it directly.
Refer this to learn how to run a sample SAML SSO application with WSO2 IS. While running that, you can monitor the HTTP Request/Response flow using a tool like SSOTracer for Firefox and understand how the communication works.
In similar to SAML SSO flow, if you are using any other authentication protocol, you first have to call the protocol specific endpoint. E.g. If you are using OAuth2 or OpenIDConnect, then you should call /oauth2 endpoint. Never /authenticationendpoint directly.
I have a couple of days following a few issues but I can not find the solution .
I have followed these issues: Custom JAX-RS authorization - using JWT in each request and
Best practice for REST token-based authentication with JAX-RS and Jersey
but I do not understand how to use filters.
I need to create a token for a android app Use the resources of my web service.
I can not just create a token and send it ?
I 'm using jjwt https://github.com/jwtk/jjwt but I think it right, a piece of code:
#POST
#Produces("application/json")
#Consumes("application/x-www-form-urlencoded")
public Response authenticateUser(#FormParam("username") String username,
#FormParam("password") String password) {
try {
// Authenticate the user using the credentials provided
// authenticate(username, password);
// Issue a token for the user
String compactJws = Jwts.builder().setSubject(username).signWith(SignatureAlgorithm.HS512, "pepe").compact();
// Return the token on the response
return Response.ok(compactJws).build();
} catch (Exception e) {
return Response.status(Response.Status.UNAUTHORIZED).build();
}
}
If anyone can help me , thanks ...
Si alguno me puede responder en castellano, mejor.
PD: Sorry if I asked the question wrong, I'm new in stackover... and sorry for my English
I am the author of the answer about token-based authentication in JAX-RS. This authentication method can be summarized in the following steps:
Exchanging hard credentials for a token
No filters are required to do it. You should have an endpoint (a JAX-RS resource method) to perform the authentication using hard credentials (like username and password). If the credentials are valid, the endpoint is going to issue a token that will be sent to the client in the response payload. The client must sent this token in the Authorization header of each request.
The endpoint that issues the tokens must not be protected, that is, no authentication must the required to access it. Once you have an Android application as client, I think you will find better consuming application/json instead of application/x-www-form-urlencoded. My answer provides details on how to do it.
Validating the token
Here the authentication filter comes into play. When using filters to validate the tokens, you can keep your endpoints lean and business focused.
The idea behind the filter is to intercept the requests to protected resources, extract the token from the Authorization header and validate it. If the token is valid, the request will proceed to the requested endpoint. If the token is invalid, the request will be aborted.
Besides the authentication filter, you can have other filters to perform authorization, for example. In the authentication filter, you must check if the token is valid and then find the user you issued the token for. In the authorization filter, you must ensure the user has enough permissions to access the requested resource. Other filters can be created according to your needs.
The code you have provided is valid to a issue a new token for a web application (uses application/x-www-form-urlencoded), but for android application It would probably be more appropriate send credentials as a json POST or in a Authorization header
After this, the client application receives the token, stores it and needs to include the JWT in every request to server. You can include the token in headers or in a request param. The server must validate the token signature, and other fields like sub (the userId) and exp (expiration time).
Using a filter, like the AuthenticationFilter provided in the example, simplifies the authentication process. It can intercept all the requests and perform the validation in a unique point. If not, you would have to validate the JWT in each method of your bussiness logic
If you have doubts about how to configure the filters I suggest to post in SO an specific question
Help! :) I'm having no end of problems trying to get the following working(apologies in advance if I'm not using the exact correct terminology) :)
I need to get a .NET web application (client) communicating with Weblogic web services secured with SAML 2 policies. There are restrictions in that I need to use .NET 3.5/4 and as such am using WIF (with the extensions) to work with ADFS2 configured to generate SAML2 tokens.
The website -> adfs2 -> SAML2 token bit is working fine so far - I definitely getting tokens through.
Additional(1) - the Weblogic services have to use SAML2 policies that implement a sender-vouches confirmation method and although ADFS 2 supplies bearer by default, I am able to manipulate the SAML assertion before we send the token across the wires to the service(s).
Additional(2) - For numerous reasons, the webservices are not reached over SSL and basicHTTPBinding is my only option.
Now the problem.. I just can't communicate with Weblogic in such a way as to send the token in the request (any logged attempt returns an oracle "General Web Service Security Error" due to there being no valid security header in the request). The preferred approach would be via WCF, using a channel factory - the code below is a rough example of what I've tried - the claimsidentity/token stuff was taken from the code sample that came with the WIF extension stuff:
IClaimsIdentity identity = Thread.CurrentPrincipal.Identity as IClaimsIdentity;
Saml2SecurityToken token = identity.BootstrapToken as Saml2SecurityToken;
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.None;
binding.Security.Transport.ClientCredentialType = HttpClientCredntialType.None;
EndpointAddress address = new EndpointAddress("http://someaddress");
ChannelFactory<weblogicService.MyService> factory = new ChannelFactory<weblogicService.MyService>(binding,address);
factory.ConfigureChannelFactory<weblogicService.MyService>();
factory.Credentials.SupportInteractive = false;
weblogicService.MyService proxy = factory.CreateChannelWithIssuedToken<weblogicService.MyService>(token)
proxy.DoSomething();
The answer at the following post (and everywhere else I've been able to find):
WCF and WebLogic SAML interop
..is exactly what I'm doing - but whether viewing the traffic with WireShark OR by implementing a customer MessageInspector and looking at the request in "BeforeSendRequest", I can't see any sign of the token (and the request is rejected as a consequence).
Also it doesn't matter if I manipulate the token to include sender-vouches or just leave it as it is originally.
Additional (3): I have been able to successfully communicate with the Weblogic service if I don't use ADFS2/SAML/WIF/WCF etc. but instead, go via a more basic WSE2.0/3.0 web references approach (i.e. creating SoapRequest, UserName token etc..)
The problem with that, is in supplying a valid username and password without user interaction. In other words, keeping a "SSO approach", and not have to implement Forms Authentication (or equivalent) to get the user credentials each time.. There doesn't appear to be any obvious way of using the SecurityToken generated by ADFS with WSE either..
Can anyone help shed some light? Why the WCF channel factory approach with a supplied token is simply not working i.e. no sign of a valid token when debugging and certainly no valid SAML token being received by Weblogic.
I have also looked at going the CustomMessageEncoder route, and adding the SAML Assertion into the SOAP header that way.. but from what I have been able to find out, it really shouldn't be this difficult. Is something in WCF broken?
End point binding limitations (basicHTTP) doesn't support SAML2 afaik, also ADFS2.0 only seems to supply bearer tokens and modifying the token after the fact is also non starter (the suggested overrides in WIF to do this don't seem to work as expected) and finally because the web services aren't behind https, having a security mode of none (which is the only one that could be used) meant no token was being sent anyway.. ahh well, back to the drawing board!
I found this in another SO thread:
Steps:
User connects to OpenID enabled website.
User enters credential information.
A POST is made with a BASE64 (website to provider)
An answer is built (that contains expiration)
The website redirects the user to the provider to login.
User enters password and submit.
Verification is done.
Login!
How are step 6-8 secured? The way I see it, the client is authenticating with the provider and reporting back the result to our server.
What is stopping the client from faking the authentication result?
Primarily, the authentication result is cryptographically signed by the provider. There are also other security measures protecting against other attacks.
Quoting the OpenID 2.0 specification, section 11.:
When the Relying Party receives a positive assertion, it MUST verify the following before accepting the assertion:
The value of "openid.return_to" matches the URL of the current request (Section 11.1)
Discovered information matches the information in the assertion (Section 11.2)
An assertion has not yet been accepted from this OP with the same value for "openid.response_nonce" (Section 11.3)
The signature on the assertion is valid and all fields that are required to be signed are signed (Section 11.4)
The client can, of course, send a fake authentication result, but it won't pass verification.