how to get SAMLResponse from request - spring-security

Can any body help me how to capture the SAMLResponse.I am using Spring SAML.
I have used below snipet in the custom filter where the authenticatinSuccesshandler sends. but getting a null.
String responseMessage = httpServletRequest.getParameter("SAMLResponse");
please advice me.

The typical use-case is to get access to the SAML assertion and this can be achieved as is described in this response. The assertion is also available in the Authentication object, you can load it using the following piece of code, for example from your authentication success handler:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
SAMLCredential credential = (SAMLCredential) authentication.getCredentials();
String assertion = XMLHelper.nodeToString(SAMLUtil.marshallMessage(credential.getAuthenticationAssertion();
The assertion is stored as an unmarshalled java object which doesn't keep all the details as received. In case you need to keep the value in exactly the same format as received (including white spaces, ...), make sure to set releaseDOM to false on WebSSOProfileConsumerImpl bean.
You can access the SAML Response object e.g. by overriding classes in bean WebSSOProfileConsumerImpl, where it's being processed inside the SAMLMessageContext object.

Related

Authentication session is not defined

I try to use Google Photos API to upload my images, base on the steps of the following link.
https://developers.google.com/photos/library/guides/upload-media
After following the Using OAuth 2.0 for Web Server Applications, I just get the Oauth2.0_token response(a JSON format with access_token, refresh_token...). However, after I put this token string with "Bearer " into request headers, the response is error 401, the error message is "code 16 Authentication session is not defined".
I cannot find any information to deal with it, thank for any help.
You probably have incorrect permissions. Make sure you request the token with the appropriate scope. For write-only access you need 'https://www.googleapis.com/auth/photoslibrary.appendonly'
src: https://developers.google.com/photos/library/guides/authentication-authorization#what-scopes
One reason this might be happening is that you initially authorized your user for read-only access. If you went through the authorization flow with a .readonly scope, your bearer token reflects that authorization (and the token is retained in your credentials file). If you change your scope but don't get a new auth token you will get this error when trying to upload. Simply redo the authorization flow with the new scope defined:
SCOPES = 'https://www.googleapis.com/auth/photoslibrary'
store = file.Storage('path_to_store')
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('google_credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
and your store will be populated with a new token that can be used for uploading.
You say you "just get the Oauth2.0_token response(a JSON format with access_token, refresh_token...)" and "put this token string with "Bearer " into request headers".
Unfortunately documentation on this isn't super clear in a lot of places. What you are supposed to provide after "Bearer" is the "access_token" field only, not the entire JSON string with all the token fields in it. For reference, this is a single string of random looking characters which probably starts with "ya29." and is pretty long - in my case it's 170 characters.

Not getting SPRING.SESSION.ID from headers

I'm using spring session and AbstractSessionWebSocketMessageBrokerConfigurer and am trying to create a STOMP Websocket with support for Spring Security and Spring Session. I can't seem to get my session activated. I use webstomp-client to connect (https://github.com/JSteunou/webstomp-client)
AbstractSessionWebSocketMessageBrokerConfigurer creates
#Bean
#SuppressWarnings("unchecked")
public SessionRepositoryMessageInterceptor<S> sessionRepositoryInterceptor() {
return new SessionRepositoryMessageInterceptor<S>(this.sessionRepository);
}
I pass as header to both the connect event and every message
SPRING.SESSION.ID:<My session id>
When I check the processing in SessionRepositoryMessageInterceptor, I see that it is trying to retrieve the session id through SimpMessageHeaderAccessor that expects the header to contain an object under header key simpSessionAttributes.
Map<String, Object> sessionHeaders = SimpMessageHeaderAccessor
.getSessionAttributes(message.getHeaders());
String sessionId = sessionHeaders == null ? null
: (String) sessionHeaders.get(SPRING_SESSION_ID_ATTR_NAME);
All the attributes that SimpMessageHeaderAccessor seems to expect are not present in the stomp client and just seem to belong to a different protocol.
How do I deal with activating a session under Stomp, Spring WebSocket, Spring Security and Spring Session? Or more specifically:
Why does SessionRepositoryMessageInterceptor use SimpleHeaderAccessor in stead of StompHeaderAcessor?
What headers do I need to pass from a javascript client to create a session (assuming I received the session id through traditional login)?
I don't know what the issue is but I can explain a few things to help you debug the issue.
Spring supports WebSocket-scoped attributes. Those are attributes that exist for as long as the session exists. The SessionRepositoryMessageInterceptor, as a HandshakeInterceptor, hooks into the initial HTTP handshake request and saves the SPRING.SESSION.ID as a WebSocket-scoped attribute. Then after the handshake, when STOMP messages start to flow, it intercepts every incoming message, and retrieves the SPRING.SESSION.ID in the websocket attributes. So I am not sure why you're trying to pass SPRING.SESSION.ID as a header. That's all managed for you as I just explained and associated with the WebSocket session.
As for the question about SimpHeaderAccessor vs StompHeaderAcessor, the former is a more generalized version. It's not wrong to use it as long it gives you enough information. In this case Spring Session doesn't care for STOMP specific details.
I don't understand your second question about what headers need to be passed from a javascript client to create a session. As long as the HTTP handshake is made within the same HTTP session it should just work. There is nothing different here from how you would do any HTTP call.

Thinktecture.Identity SAML token unauthorized

I am using the Thinktecture.IdentityModel 4.0 samples for WebApiSecurity. I've modified the AdfsSamlClient to use our ADFS Server. I am able to get a SAML token from out ADFS Server using
var channel = factory.CreateChannel();
var token = channel.Issue(rst) as GenericXmlSecurityToken;
Then I try to make the service call
var client = new HttpClient { BaseAddress = _baseAddress };
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("AdfsSaml", saml);
var response = client.GetAsync("identity").Result;
And get a 401 - Not Authorized call.
I am not sure how to debug this. I have tracing for Microsoft.IdentityModel, but it is only information level trace, no errors or warnings, and nothing I am able to use to debug.
The interesting part of the service trace:
1.
Description OnEndRequest is redirection to IdentityProvider '/WebHost/api/identity'
2.
Description CreateSignInRequest
BaseUri https://[ADFS...]/adfs/ls/
wa wsignin1.0
wtrealm https://[WorkStation...]/WebHost/
wctx rm=0&id=passive&ru=%2fWebHost%2fapi%2fidentity
3.
Description Redirecting to IdentityProvider: 'https://[ADFS...]/adfs/ls/?wa=wsignin1.0&wtrealm=https%3a%2f%2f[WorkStation...]%2fWebHost%2f&wctx=rm%3d0%26id%3dpassive%26ru%3d%252fWebHost%252fapi%252fidentity&wct=2013-09-30T17%3a35%3a04Z'
Thanks for any insight.
Main thing that springs to mind is to make sure the server knows how to handle the "AdfsSaml" scheme that you're using, so you'll want to make sure that your mapping is correct to your token handler.
One thing I tried was to create my own token handler, and mapped that as the token handler for the header. If you want, you can start with Thinktecture's own HttpSamlSecurityTokenHandler, and debug your way through that. Obviously, if it never hits it, then you've got a mapping issue somewhere.
I also found that if an exception was thrown in the ClaimsAuthenticationManager, it would report as unauthorized - even though the exception being thrown was something completely unrelated (in my case, an InvalidCastException). That stumped me for a while, because I hadn't realise that authentication had gotten so far down the pipeline and that validation of the token had actually been successful - I was just checking the HTTP response, which kept saying unauthorised - so make sure you're not being misled by anything trivial like that.

Invoke WCF Data Services Service Operation from iOS

How do I invoke a Service Operation in WCF from iOS?
I have a Service Operation defined in my WCF Data Service (tied to a stored procedure in my DB schema) that I need to invoke from iOS. Say I've got the following declaration in my .svc.cs file:
[WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
public IQueryable<Foo> GetFoos(int param1, DateTime param2, string param3)
{
return CurrentDataSource.GetFoos(param1, param2, param3).AsQueryable();
}
And I've got it set up with the proper rights in InitializeService:
config.SetServiceOperationAccessRule("GetFoos", ServiceOperationRights.AllRead);
When I try to invoke this via HTTP POST from iOS, I get back an error wrapped in JSON:
Bad Request - Error in query syntax.
It seems like it doesn't like how I'm passing my parameters. I'm passing them JSON-encoded (using NSJSONSerialization to turn an NSDictionary into a JSON string) in the request body of a POST request. The same method works on another web service (.svc) not connected to WCF that has operations annotated the same way.
An answer to another question of mine in a similar vein suggests that data formats can be negotiated between client and server, and I've read that dates are a pain to format, so maybe it's my DateTime parameter that's a problem. But I've tried both the JSON format (\/Date(836438400000)\/ and /Date(836438400000)/) and the JSON Light format (1996-07-16T00:00:00) to no avail.
So my question is this: what is the proper way to invoke this operation? If I need to have my app tell the server what format to expect, how do I do that?
Update: I tried using the format datetime'1996-07-16T00:00:00' as mentioned in this question. Same error.
Update 2: The MSDN page for Service Operations seems to suggest that nothing besides Method = "POST" is supported when annotating the WebInvoke for a Service Operation. I tried removing everything from what is quoted in the above code and setting the method to POST. Same error.
Update 3: On Pawel's suggestion, I made a new Service Operation on my Data Service just like this:
[WebInvoke(Method = "POST")]
public IQueryable<string> GetFoos()
{
List<string> foos = new List<string>();
foos.Add("bar");
return foos.AsQueryable();
}
I was able to make it work in Fiddler's Composer pane by setting the method to POST, adding accept:application/json;charset=utf-8 and Content-Length:0 to the headers. Then I added a single int parameter to the operation (called param1). I set the body of my request in Fiddler to {"param1":"1"} and ran it (and Fiddler automatically updated my content-length header), and got the same error. I changed the type of my parameter to string and ran my request again and it worked. So my problem seems to be non-string types.
You need to send parameters in the Url and not in the request body.

ServiceAuthorizationManager exception always sending xml response

I have a custom ServiceAuthorizationManager implemented in wcf webhttp service to do api key verification. It sends a webfaultexception with the code 403 if the key is invalid.
But the issue is, when the exception is thrown, it s always send to the client as xml.
The service accepts both JSON and XML and it s working fine for all the other operations except for the exception from the manager.
No matter if I set the accept header or content type the result is always xml. But for other requests, the response type switches perfectly according to the content-type header
Here's the web.config
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
Any help is really appriciated.
If anyone else ran into this issue: looks like no way to fix it. The solution I did was to do the verification in the service's constructor. Make sure the instance context mode is set to per call.
More info http://amilagm.com/2012/04/better-way-to-do-api-key-verification-in-wcf-webhttp-services/

Resources