How to send a SAML Request? - java

i want to send a SAML request to my IDP (Azure AD) but ia m not sure how to send the request at all.
First i used OpenSAML to build an AuthRequest. Which i encoded as a String.
Now i wanted to use ApacheHttpClient to send the request and read the response and i am not sure if OpenSAML provides http sending methods at all so my idea was to use Apaches HttpClient for this for now.
String encodedAuthRequest = generateAuthRequest();
String url = "http://myidp/samlendpoint";
CloseableHttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
// add request header
request.addHeader("User-Agent", USER_AGENT);
// what is to add else?
HttpResponse response = client.execute(request);
I am stuck now since i am not sure how to setup the request, does it need to be a query parameter like ?saml=.... in GET or do i have to put the encoded saml response in the body as POST..
Can someone help or clarify these issue?
Update from Guillaumes answer:
I have this from the IDPs MetaData:
<IDPSSODescriptor>
<SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="https://myidp/saml2" />
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://myidp/saml2" />

Depends on which binding you are supposed to use. The IdP documentation or metadata should mention that. There are several:
Redirect Binding (using a GET), by far the most common for Requests
POST Binding
Artifact Binding (more complex, but I have never seen it used for Requests)
...
I suppose that Redirect Binding will be used in your case (EDIT: you added the metadata from your IdP, it mentions that you can use both Redirect and POST bindings). It is described here: https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf page 15.
Short version: your must first use the DEFLATE algorithm to compress your XML Request, encode it using base64, encode it using URL encoding, then pass it as a query parameter named SAMLRequest
?SAMLRequest=<your url-encoded base64-encoded deflated authnrequest>
https://en.wikipedia.org/wiki/SAML_2.0#SP_Redirect_Request.3B_IdP_POST_Response

Related

Need to send https GET request with oauth

I'm new to OAuth and trying to send a https GET request to retrieve something. Earlier I was using POSTMAN to test that and I was able to execute the GET request with OAUth 1.0 header authorization. The header authorization looks something as
Authorization: OAuth oauth_consumer_key="xxxxxxxxxxxxxxxxxxx" ,oauth_signature_method="HMAC-SHA1" ,oauth_timestamp="1409861973" ,oauth_nonce="x1409861973681" ,oauth_version="1.0" ,oauth_signature="M+Dq62XboEd3+t6VDIcLy86zlQg="
The query looks something as
https://secure.api.abc.net/DataService/data/ServiceAccount?schema=1.0&form=json&byBillingAccountId={EQUALS,yyyyy}
Note that I'm able to execute this fine from POSTMAN.
Now, I need to code that in java and I'm able to generate the oauth signature fine, but I'm wondering how do I set the authorization header after that in a https request???
Please advise as I'm new to oauth and want to learn.
I guess if your doing in Java, you will need to use the Apache HttpClient or something similar to make that request to the server and set the OAuth header to the request.
Code sample using the Apache HttpClient below.
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
// add request header
request.addHeader("OAuth", oauthHeaderString);
HttpResponse response = client.execute(request);

How to pass data in HTTP Header while redirecting a request in Java

is it possible to pass some data in HTTP Header, while redirecting a request from one server to another.
Here is my scenario,
I have one generic filter, via which every request is passing.
Now, based on some condition, I'm redirecting the request to some different server using the API objHttpServletResponse.sendRedirect(strURL).
But, the issue is, when I'm setting some data in response header like objHttpServletResponse.setHeader("Key", "Value"); That's not available in the redirected server.
So, my questions are,
1. Is there any way to pass some data in header while redirecting a request?
2. If not, what are the other possible ways to send some data while redirecting a request?
Please Note: few other ways, like
using URL parameters:
objHttpServletResponse.sendRedirect(strURL+"?param="+ strParamValue);
or
using session:
HttpSession session = httpRequest.getSession();
session.setAttribute("Key", "Value");
is not what I'm expecting.
The headers you set are written to the response that gets sent to the client, along with a Location header and a status code. See Redirecting a request using servlets and the "setHeader" method not working
The client is then supposed to send an identical request to the URL you specified in the Location header. Identical to the request it sent to you.
You want the browser to send a header you specify along with the redirected request. Have you considered adding a (domain) Cookie header? Some googling leads me to believe that cookies set in a redirect response will get picked up by most browsers. See http://blog.dubbelboer.com/2012/11/25/302-cookie.html
Please have a look at Apache HttpClient.
This example adds several parameters to the post request :
String url = "https://selfsolve.apple.com/wcResults.do";
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(url);
// add header
post.setHeader("User-Agent", USER_AGENT);
List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("sn", "C02G8416DRJM"));
urlParameters.add(new BasicNameValuePair("cn", ""));
urlParameters.add(new BasicNameValuePair("locale", ""));
urlParameters.add(new BasicNameValuePair("caller", ""));
urlParameters.add(new BasicNameValuePair("num", "12345"));
post.setEntity(new UrlEncodedFormEntity(urlParameters));
HttpResponse response = client.execute(post);
System.out.println("Response Code : "
+ response.getStatusLine().getStatusCode());
The problem is that the redirect() method of the response initiates a new request altogether, thereby loosing the attributes that were set before redirecting. Luckily there is a fluent way of solving the problem still.
response.setHeader("Key", "Value");
request.getRequestDispatcher("redirecturl").forward(request, response);
Then in your destination you can do
response.getHeaders("key")
You can use JS redirect, i.e. instead of calling sendRedirect return HTML page with embedded javascript that will do redirect setting headers you need.
However, using GET parameters is really the best solution. If you have concerns about users altering parameters manually - use MAC code to protect parameters.See
Message authentication code
In simplest form, ?p1=1&p2=2&mac={mac value}, where {mac value} = md5('MY_SECRET_KEY' + 'p1=1&p2=2').
Receiving side can recalculate MAC and compare it with provided one. Since external users can not know 'MY_SECRET_KEY', they will not be able to make valid MAC.
Have you checked the HTTP request/response from/to server? You can use a number of plugins on chrome or firefox to check that. You would be able to see if value is being passed from your server to another server or not
Also retrieve the header using httpResponse.getHeader("Key"); not using request.getHeader("key"). One of my colleague was facing same issue some days back, he was using request to fetch header values

Send xml as part of URL request in Java

This might be a trivial question but I'm trying to send web request to USPS to get a http post response (or email response depending on my request) containing the tracking information based on the tracking number that I send in. The documentation says the xml needs to appended as part of the url like below
http://secure.shippingapis.com/ShippingAPITest.dll?API=TrackV2&XML=<PTSEmailRequest USERID="xxxxx"><TrackId>xxxxx</TrackId><RequestType>EN</RequestType></PTSEmailRequest>
I saw there were 2 ways to make an xml request, one using HttpPost and the other URLConnection. I'm a bit thrown by how I go about this and I'm failing to appreciate what's the difference between appending xml in the url and a normal http request. Can someone please clear things up for me?
USPS documentation for tracking =>
https://www.usps.com/business/web-tools-apis/track-and-confirm.pdf
I read these related Stackoverflow posts
Java: How to send a XML request?
posting XML request in java
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("http://secure.shippingapis.com/ShippingAPITest.dll");
List<String> params = new ArrayList<String>(2);
params.add(new BasicNameValuePair("API", "TrackV2"));
params.add(new BasicNameValuePair("XML", FuncTOGenerateXML()));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
//.....
// .....
instream.close();
}
An HTTP request can use one of several methods, like POST, GET, DELETE, PUT... Here we talk about POST and GET
Technical differences
With GET, the data is retrieved from the parameters in the URL.
With POST, the data is retrieved from the data transmitted inside the HTTP message.
Intended use differences
GET is intended to be used when the request does not cause a change (v.g., searching in Google). Since you can repeat the request without side effects, the data is in the URL and can be stored in the browser history, favorites, etc.
POST is intended to use when you are performing a change (v.g. sending an e-mail, doing a on-line purchase). The data related is not stored with the URL (it is then that, if you go back to a page that was obtained using POST, the browser many times will show you a pop-up asking for permission to send the data again.
In real usage, the distinction is not so clear cut, in particular POST is sometimes used when the data is too large (URLs have limited length). Also, sometimes GET is used with the meaning of POST so the data can be presented as an HTML link.
Finally, URLConnection is the basic API for opening a connection (which you can use as a POST or GET request, based in how you pass the data, or something else) and HttpPost is just a higher level API for creating a POST request. If you go the basic way, use HttpURLConnection better.

How to send "parameters" to all HTTP request methods?

I'm trying to write a Java client (with Apache HttpClient) for the Gengo API which makes use of HTTP GET, POST, PUT and DELETE. However for every RESTful API "method" that they expose, you must pass your API key and signature as "parameters".
Would this mean query string parameters, POST variables, key-value pair headers, or something else?
I guess I'm just confused by what is meant by the word "parameters" in the context of all these different HTTP request methods. In other words, how would I pass the API key as a "parameter" to their API when I could be using GET, POST, PUT or DELETE? My understanding was that only HTTP GET can handle query string params, and that HTTP POST can only handle POST variables. And I have never used PUT or DELETE before so I'm not sure what they require.
So I ask: what mechanism can I use to send the API key/signature via all 4 types of request methods, or do they all support the processing of query string parameters? Thanks in advance.
You can try this. It works for my HttpClient application with POST request.
DefaultHttpClient httpClient = new DefaultHttpClient();
httpClient.getParams().setParameter(name, value);
......
For Example, I set the connection timeout:
httpClient.getParams().setIntParameter(HttpConnectionParams.CONNECTION_TIMEOUT, httpTimeout);
Then later, to send(execute) the request:
HttpResponse response = httpClient.execute([My HttpPost instance was here, but I think you can use HttpGet, HttpPut, and HttpDelete here as well]);
All verbs can use request parameters (also known as query parameters) and they will be available to the server in the same way regardless of if you also send a body.
In your example (Gengo) there is a good example on there page about authentication.

How can I POST using Java and include parameters and a raw request body?

I am communicating with a web service that expects a POST parameter and also expect Request body. I have confirmed that such a POST request can be done using a REST Console I have, but I am unable to make such a request in Java using Apache libraries.
In the code below, I am able to POST to the web service, and it correctly receives the contents of the variable raw_body. If I uncomment the first of the two commented lines, the web service receives the "fname" parameter, but it no longer receives the body of the POST.
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
...
HttpClient httpClient = new HttpClient();
String urlStr = "http://localhost:8080/MyRestWebService/save";
PostMethod method = new PostMethod(urlStr);
String raw_body = "This is a very long string, much too long to be just another parameter";
RequestEntity re = new StringRequestEntity(raw_body, "text/xml", "UTF-16");
//method.addParameter("fname", "test.txt");
//httpClient.getParams().setParameter("fname", "test.txt");
method.setRequestEntity(re);
How can I transmit both the parameter and the body?
You could use the setQueryString method to add the parameters to the URL that is being POSTed to. From a RESTful perspective I'd argue you should normally not be doing that, however, since a POST should represent a call to a resource and anything that would qualify for a query parameter should be included in the representation that is being transferred in the request body...or it should represent qualification of the resource itself in which case it should be part of the path that is posted to which could then be extracted by the controller using #PathVariable/#PathParam or something similar. So in your case you could also be looking for something like POST /MyRestWebService/files/test.txt or more fittingly a PUT if you're saving the resource and know the URI. The code on the server could pull the filename out from a URL pattern.
You need to make a POST request using multipart-form. Here is the example:
Apache HttpClient making multipart form post
Alternatively, you can make a POST request with the content (parameters and files) encoded using application/x-www-form-urlencoded but it is not recommended when you want to make a POST request with large content, like files.

Categories

Resources