Unable to retrieve post data using ,@Context HttpServletRequest when passed to OAuthTokenRequest using Oltu
Asked Answered
C

3

16

I'm using Oltu for Oauth2.

When using @Context HttpServletRequest request I am unable to retrieve post data

When I am using @FormParam I am able to retrieve post data.

On passing request to OAuthTokenRequest

OAuthTokenRequest oauthRequest = new OAuthTokenRequest(request);

I am getting following error

{"error":"invalid_request","error_description":"Missing grant_type parameter value"}

When debugging on the oltu OAuthTokenRequest class following code is used to retrive param value

public String getParam(String name) {
        return this.request.getParameter(name); // from request it is unable to get post data.As i am getting request object using  @Context HttpServletRequest request .
    }

It is said that using @Context HttpServletRequest request it is not possible to get post data for using @Context HttpServletRequest request So, my question is

How to get HttpServletRequest request with post data in jax-ws so that I can pass HttpServletRequest request to OAuthTokenRequest This is my code

@Path("/token")
public class TokenEndpoint {

 @POST
    @Consumes("application/x-www-form-urlencoded")
    @Produces("application/json")
    public Response authorize(@FormParam("state") String state,@Context HttpServletRequest request) throws OAuthSystemException {
        try {
        // here I am unable to get value of request.getParameter("state") 
       // but using (@FormParam("state") I am able to get value of post parameter state
            request.getParameter("state");
            // exception is thrown from following code 
            OAuthTokenRequest oauthRequest = new OAuthTokenRequest(request);
Chappy answered 13/3, 2014 at 11:13 Comment(0)
B
20

Found a workaround (read the comments).

OLTU Issue #26

Jersey is consuming the POST data.
The solution is to wrap the HttpServletRequest and override getParameters().
This is the wrapper:

public class OAuthRequestWrapper extends HttpServletRequestWrapper {

    private MultivaluedMap<String, String> form;

    public OAuthRequestWrapper(HttpServletRequest request, MultivaluedMap<String, String> form)
    { super(request); this.form = form; }

    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (value == null)
        { value = form.getFirst(name); }
        return value;
    }
}

And this is how to implement the token POST method:

@POST
@Path("/token")
@Consumes("application/x-www-form-urlencoded")
@Produces("application/json")
public Response token(@Context HttpServletRequest request, MultivaluedMap<String, String> form) {   

    [...]

    OAuthTokenRequest oauthRequest = new OAuthTokenRequest(new OAuthRequestWrapper(request, form));

    [...]

}
Bulbul answered 20/3, 2014 at 17:17 Comment(3)
Thank goodness I finally see you answer. This has taken me hours.Morale
@Matteo Pacini, After searching for a solution in the dark, I stumbled upon this thread... Got it working... Thanks a lot for posting the solution here! :)Iotacism
Excellent work, thank you! The key to this answer for me was learning that it was trivial to add the MultivaluedMap to the endpoint method and the jax-rs service (Jersey in my case) would provide the parameters there. I didn't need to necessarily create the request wrapper, the key was simply finding where the raw form data could be found!Groenendael
U
2

There's also the issue of the resource server endpoint failing to retrieve token values from post requests (jersey as jax-rs implementation), this is because validator interface implementations in the resource server code use

httpServletRequest.getParameterValues(param);

this issue can be worked around by overriding String[] getParameterValues(String) in the same HttpServletRequestWrapper proposed by Matteo, note the extra condition, it's important for catching empty token requests (the method should return null if no token is passed):

@Override
public String[] getParameterValues(String name) {
    String[] values = super.getParameterValues(name);
    if(values == null && form.get(name) != null){
        values = new String[form.get(name).size()];
        values = form.get(name).toArray(values);
    }
    return values;
}

relevant in apache oltu 1.0.0

Unpremeditated answered 13/8, 2014 at 13:7 Comment(1)
Excellent work, thank you! The key to this answer for me was learning that it was trivial to add the MultivaluedMap to the endpoint method and the jax-rs service (Jersey in my case) would provide the parameters there. I didn't need to necessarily create the request wrapper, the key was simply finding where the raw form data could be found!Groenendael
G
0

I found another option to this limitation of not being able to get the parameters required for oltu in a JAX-RS handler.

Instead of using a HttpServletRequestWrapper object, simply call the HttpServletRequest.getParameterMap() method inside of your WebFilter implementation. This will load the request object's cached parameter map with all of the request's parameters, making these parameters available for the life of this request object.

I prefer this method since it makes the JAX-RS handler cleaner, and I'm already using a WebFilter to deny access to all non-oauth requests without a valid token.

I've verified this works in both Jersey and CXF.

Gnatcatcher answered 30/3, 2016 at 18:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.