I'm building my oauth2-protecet webservice, and a client. For webservice I used spring security implementation, and used this as example. For client I'm trying out apache oltu library. Here's my snippet:
OAuthClientRequest request = OAuthClientRequest.tokenLocation
("http://localhost:8080/oauth/token")
.setGrantType(GrantType.CLIENT_CREDENTIALS)
.setClientId("clientapp")
.setClientSecret("123456")
.buildHeaderMessage();
OAuthAccessTokenResponse oAuthResponse = cli.accessToken(request);
System.out.println(oAuthResponse.getAccessToken());
It does not work. While this
curl -X POST -vu clientapp:123456 --data "grant_type=client_credentials&client_secret=123456&client_id=clientapp" http://localhost:8080/oauth/token
works perfectly well. Here's the curl request:
POST /oauth/token HTTP/1.1
Authorization: Basic Y2xpZW50YXBwOjEyMzQ1Ng==
User-Agent: curl/7.35.0
Host: localhost:8080
Accept: */*
Content-Length: 70
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_secret=123456&client_id=clientapp
as you can see, I used Basic authentication with curl and it worked(even though suggested authentication type is Bearer).
And here's oltu packet:
POST /oauth/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer client_credentials123456clientapp
User-Agent: Java/1.8.0_51
Host: localhost:8080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 4
null
I'm nor sure how bearer authorization is supposed to work, but this packet looks all wrong.
I also tried to use buildBodyMessage() and buildQueryMessage() instead of buildHeaderessage() as was suggested in this post, but it's no good either.
This line doesnt look very healthy:
Authorization: Bearer client_credentials123456clientapp
I created a test server with Oltu, basically a servlet:
OAuthResponse oauthResponse = OAuthASResponse
.tokenResponse(HttpServletResponse.SC_OK)
.setAccessToken(accessToken)
.setExpiresIn(Integer.toString(expires))
.setRefreshToken(refreshToken)
.buildJSONMessage();
response.setStatus(oauthResponse.getResponseStatus());
response.setContentType("application/json");
And for the client I got:
OAuthClientRequest request = OAuthClientRequest
.tokenLocation("http://localhost:8083/OltuServer/token")
.setGrantType(GrantType.CLIENT_CREDENTIALS)
.setClientId("clientapp")
.setClientSecret("123456")
.buildQueryMessage();
OAuthAccessTokenResponse oAuthResponse = oAuthClient.accessToken(request);
System.out.println(oAuthResponse.getAccessToken());
The main difference from your code is buildQueryMessage(). Using buildHeaderMessage() I get an exception on the server
OAuthProblemException {error='invalid_request', description='Missing grant_type parameter value' ... }
But I see that Oltu is at version 1.0.1 now while I've been testing on 1.0.0. That version might behave different.
The following appeared to work for me:
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
OAuthClientRequest bearerClientRequest = OAuthClientRequest.tokenLocation("http://localhost/rest/auth")
.setUsername("userid")
.setPassword("Password01")
.buildQueryMessage();
bearerClientRequest.setHeader(OAuth.HeaderType.CONTENT_TYPE, "multipart/form-data");
OAuthResourceResponse resourceResponse = oAuthClient.resource(bearerClientRequest, OAuth.HttpMethod.POST, OAuthResourceResponse.class);
Related
With a given token, Postman can hit the Microsoft Graph API successfully, whereas the SpringBoot RestTemplate gives the 403 Forbidden error.
From Postman:
GET https://graph.microsoft.com/beta/me/profile/
Authorization: Bearer <token>
User-Agent: PostmanRuntime/7.26.8
Cache-Control: no-cache
Host: graph.microsoft.com
Accept-Encoding: gzip, deflate
Connection: keep-alive
Accept: */*
From SpringBoot Apache Logs:
GET /beta/me/profile/ HTTP/1.1
Authorization: Bearer <token>
Cache-Control: no-cache
User-Agent: PostmanRuntime/7.26.8 (I hardcoded it to make everything same as postman)
Host: graph.microsoft.com
Connection: Keep-Alive
Accept-Encoding: gzip,deflate
Accept: */*
Here is the sample code that I was using:
#GetMapping("/test")
public String test() {
String token = "removed for now";
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setBearerAuth(token);
httpHeaders.setAccept(Arrays.asList(MediaType.ALL));
httpHeaders.setCacheControl("no-cache");
httpHeaders.add(HttpHeaders.USER_AGENT, "PostmanRuntime/7.26.8");
HttpEntity httpEntity = new HttpEntity(httpHeaders);
ResponseEntity<String> exchange = restTemplate.exchange("https://graph.microsoft.com/beta/me/profile/",
HttpMethod.GET,
httpEntity,
String.class);
return exchange.getBody();
}
I tried several suggestions but couldn't figure it out. Any idea on what might be going wrong?
I am trying to do a $batch request in Java using OData v2.
An example request from the browser would be something like below between the double quotes.
But how can I make this request programatically? Is there a sample call somewhere? Any help is appreciated.
Request URL: https://someUrl/project/odata/project/FOLDER/$batch
Request Method: POST
Status Code: 202 Accepted
Remote Address: 1.2.3.4:1234
Referrer Policy: no-referrer-when-downgrade
content-encoding: gzip
content-length: 5256
content-type: multipart/mixed; boundary=E828EB257B134AC6F567C8D3B67E666E1
dataserviceversion: 2.0
Accept: multipart/mixed
Accept-Encoding: gzip, deflate, br
Accept-Language: en
Connection: keep-alive
Content-Length: 595
Content-Type: multipart/mixed;boundary=batch_4edb-a2cd-948d
Cookie: project-usercontext=project-language=EN&project-client=100;
--Some cookie content--
DataServiceVersion: 2.0
Host: host.myClient.com:1234
MaxDataServiceVersion: 2.0
Origin: https://host.myClient.com:1234
Referer: https://host.myClient.com:1234/project/index.html
project-cancel-on-close: true
project-contextid-accept: header
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/1.2.3.4 Safari/537.36
x-csrf-token: 8Fd53yy2vuCjnaFKrZNuLg==
--batch_4edb-a2cd-948d
Content-Type: application/http
Content-Transfer-Encoding: binary
GET MyEntityDetailsSet HTTP/1.1
project-contextid-accept: header
Accept: application/json
Accept-Language: en
DataServiceVersion: 2.0
MaxDataServiceVersion: 2.0
project-cancel-on-close: true
> --batch_4edb-a2cd-948d
Content-Type: application/http
Content-Transfer-Encoding: binary
GET MyObjectSet HTTP/1.1
project-contextid-accept: header
Accept: application/json
Accept-Language: en
DataServiceVersion: 2.0
MaxDataServiceVersion: 2.0
project-cancel-on-close: true
--batch_4edb-a2cd-948d--
You can use Olingo V2 as an OData client (although a rather ugly one in my opinion). There is a full tutorial dedicated to this usage on the official Olingo site: How to use Apache Olingo as client library.
Olingo knows to build requests and parse responses, but you need an underlying mechanism to execute the HTTP calls. My recommendation would be to not rely on manually opening HttpURLConnections like in the above example, but to use something like Apache Http Client or some other dedicated library instead (in order to reduce the amount of code you write and also to have access to more advanced concepts like connection polling).
In a nutshell, you must first read and parse the metadata of the service that you want to consume:
// content = read the metadata as an InputStream
Edm dataModel = EntityProvider.readMetadata(content, false);
You can build a batch request via a fluent-style API:
BatchQueryPart part = BatchQueryPart.method("GET")
.uri("/Employees('1')")
.build();
// here you could have a larger list of parts, not just a singleton list
InputStream payload = EntityProvider.writeBatchRequest(
Collections.singletonList(part), "batch_boundary");
Then you have to just execute it using your HTTP request execution mechanism of choice (method = "POST" and body = the payload variable). Afterwards, you can parse the obtained response using Olingo:
// body = the response body received
// contentType = the Content-Type header received
List<BatchSingleResponse> responses =
EntityProvider.parseBatchResponse(responseBody, contentType);
// you can obtain the body for each request from the response list
String partBody = responses.get(0).getBody();
InputStream partStream = new ByteArrayInputStream(partBody.getBytes());
String partType = responses.get(0).getHeader(HttpHeaders.CONTENT_TYPE);
Lastly, using the Edm from the first step you can also parse each individual body based on the type of request that you build. For example you could use the readEntry method to de-serialize a single entity read:
// first we have to find the entity set you used to make the request
EdmEntitySet entitySet = edm.getDefaultEntityContainer()
.getEntitySet("Employees");
ODataEntry entry = EntityProvider.readEntry(partType, entitySet,
partStream, EntityProviderReadProperties.init().build())
Lastly, you can use the entry methods to get e.g. the properties.
As I read Jax-ws can authenticate with NTLM, but I have a problem;
First of all I create MyAuthenticator java class as describe in java documentation(see:
http://docs.oracle.com/javase/7/docs/technotes/guides/net/http-auth.html).
when I try to connect with soapUI everything is Ok, see request header:
Request Headers Value
(Request-Line) POST /Online/OnlineServices.asmx HTTP/1.1
Content-Type text/xml;charset=UTF-8
SOAPAction "http://CTL.COM/OnlineServices/AcquireTicket"
Host 172.22.2.144:8000
Connection Keep-Alive
User-Agent Apache-HttpClient/4.1.1 (java 1.5)
Authorization NTLM TlRMTVNTUAADAAAAGAAYAEAAAACgAKAAWAAAAAYABgD4AAAAGAAYAP4AAAAMAAwAFgEAAAAAAAAiAQAA
Accept-Encoding gzip, deflate
Content-Length 702
when I try to connect with java, I got 500 Internal server error, see header:
Request Headers Value
(Request-Line) POST /Online/OnlineServices.asmx HTTP/1.1
SOAPAction "http://CTL.COM/OnlineServices/AcquireTicket"
Accept text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Content-Type text/xml;charset="utf-8"
User-Agent JAX-WS RI 2.1.4-b01-
Host 172.22.2.144:8000
Connection keep-alive
Authorization NTLM TlRMTVNTUAADAAAAGAAYAIwAAAD8APwApAAAAAYABgBYAAAAIgAiAF4AAAAMAAwAgAAAAAAAAACgAQAABYKIogoAOTgAAAAP5/lqdc43ElnLlEh5ASEkQlUARgBDAGUAdgBnAGUAbgBpAC4AbwByAG0AbwB0AHMAYQBkAHoAZQBQAEMALQAyADMAMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABXZ
Accept-Encoding gzip, deflate
Content-Length 443
this is my code :
Authenticator.setDefault(new MyAuthenticator(domain + "\\kuser","kpass"));
OnlineServicesSoap onlineServicesSoap = new OnlineServices(url,qName).getOnlineServicesSoap();
Map<String, List<String>> headers = new HashMap<String, List<String>>(); headers.put("Content-Type", Collections.singletonList("text/xml;charset=UTF-8"));
headers.put("Accept-Encoding", Collections.singletonList("gzip, deflate"));
((BindingProvider)onlineServicesSoap).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, headers);
try {
AcquireTicketResponse acquireTicketResponse =
onlineServicesSoap.acquireTicket(acqTicket);
} catch (RuntimeException ex) {
System.out.println(ex.getMessage() + ex.getCause());
}
I searched a lot and found some posts suggesting to do NTLM authentication but I couldn't to connect.. I don't want to use axis implementation
I have a web application that use Angularjs on frontend och Resteasy + Jackson on the back end. I'm sending a file from Angular component to a REST method, receiving method looks like this :
#POST
#Path("/upload/attachment/for/{eventId}")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(MultipartFormDataInput input,
final #PathParam("eventId") Long eventId,
#Context HttpServletRequest request) {
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
...my awesome stuff...
return Response.ok().build();
}
And request has following headers when sent :
Accept application/json, text/plain, */*
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Content-Length 347085
Content-Type multipart/form-data; boundary=---------------------------12164806981346771846716776342
Cookie JSESSIONID=aoBd1hgzR3GM8bSG5P-9g-vQ; csrftoken=ziQ7kN7TlMehR2aURDrmaMLYAroMsSpu
Host localhost:9000
Referer http://localhost:9000/local/myapp/index.html
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:32.0) Gecko/20100101 Firefox/32.0
The problem is that THIS request ALWAYS has application/json as a Content-Type instead for multipart/form-data as it says in the headers. And I get :
20:12:00,490 WARN [org.jboss.resteasy.core.SynchronousDispatcher] (http-/127.0.0.1:8080-2) Failed executing POST /events/upload/attachment/for/null: org.jboss.resteasy.spi.UnsupportedMediaTypeException: Cannot consume content type
Already in HttpServletDispatcher the content is wrong.
I can't get if this is JBOSS that set Content-Type to wrong value or some thing else.
Ok, it was that I have an extra layer between angular and server which runs on Node.js and it just tunel requests to the server. I had to add following :
var r = null;
r = request.put({uri: url, json: inReq.body, headers: inReq.headers, form: inReq.form});
inReq.pipe(r).pipe(inRes);
This set all the headers from outgoing request and tunnel the request
Now I have right content-type
Hi I'm trying to create a soap client using spring-ws. I tried whith the following code:
public void test1() {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
webServiceTemplate.setDefaultUri("the url of my web service");
StreamSource source = new StreamSource(new StringReader("<message xmlns=\"http://tempuri.org\">Hello Web Service World</message>"));
StreamResult result = new StreamResult(System.out);
webServiceTemplate.sendSourceAndReceiveToResult(source, result);
}
from http://docs.spring.io/spring-ws/site/reference/html/client.html and I got this excetion.
org.springframework.ws.soap.client.SoapFaultClientException: Operation 'message' is not defined in the WSDL for this service
at org.springframework.ws.soap.client.core.SoapFaultMessageResolver.resolveFault(SoapFaultMessageResolver.java:37)
at org.springframework.ws.client.core.WebServiceTemplate.handleFault(WebServiceTemplate.java:774)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:600)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:537)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:492)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:436)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:427)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:417)
at Test.test1
How to fix it ?
Ok I solve it, in the question there is juste an exemple of a case where the error occured,
I used netcat as client and got this result:
POST / HTTP/1.1
Accept-Encoding: gzip
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
SOAPAction: ""
Content-Type: text/xml; charset=utf-8
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.7.0_55
Host: localhost:1234
Connection: keep-alive
Content-Length: 154
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><message xmlns=\"http://tempuri.org\">Hello Web Service World</message></SOAP-ENV:Body></SOAP-ENV:Envelope>
In this test the message was not what the server was expecting. But I understood the problem.
I thought that spring ws wasn't creating the soap envelope, so the message had two envelopes.