Liferay 7.2 Rest Service read headers of request - rest

I have Liferay 7.2.
I created a module rest.
I created a method GET
I want to read headers of incoming request.
I need to read authentication bearer token.
how can i do that?
This is my example code
#GET
#Path("/get-request-headers")
public String jsonGetRequestHeaders() throws Exception {
String authtoken = ?????;
return authtoken;
}

I found the solution:
#GET
#Path("/get-request-headers")
public String jsonGetRequestHeaders(
#HeaderParam("Authorization") String token
) throws Exception {
String authtoken = token;
return authtoken;
}

Related

Rest Assured: Why do I get IllegalStateException exception?

I am in the process of studying Rest-Assured framework.
I am using http://ziptasticapi.com free API for my drills.
When I call:
final static String BASE_URI = "http://ziptasticapi.com/";
final static String ADAK_ZIP_CODE = "99546"; //{"country":"US","state":"AK","city":"ADAK"}
final static String ATKA_ZIP_CODE = "99547";
public static final String GET_METHOD = "GET";
RestAssured.baseURI = BASE_URI;
String responseString = when().get(ADAK_ZIP_CODE).then()
.statusCode(200)
.and()
.extract()
.asString();
System.out.println(responseString);
I get the following string:
{"country":"US","state":"AK","city":"ADAK"}
as responseString value.
When I am trying:
RestAssured.baseURI = BASE_URI;
ZipData zipdata = when().get(ADAK_ZIP_CODE).then()
.statusCode(200)
.and()
.extract()
.as(ZipData.class);
public class ZipData {
public String country;
public String state;
public String city;
}
I crash on :
java.lang.IllegalStateException: Cannot parse object because no
supported Content-Type was specified in response. Content-Type was
'text/html;charset=UTF-8'.
Why is that? Could it be the rest returns an Html and not Json? How do I handle this?
Thanks!
First of all, keep in mind that REST Assured is a HTTP client primarily designed for testing HTTP APIs. So let me highlight that you shouldn't use REST Assured for anything other than testing.
Looks like the endpoint you are attempting to consume is returning a JSON document in the response payload, but the value of the Content-Type header is text/html;charset=UTF-8, so REST Assured cannot parse the response as a JSON document and convert it to an instance of ZipData. That's not what you expect from a sound HTTP API.
You could work around it and write a filter to override the Content-Type header, as show below:
public class OverrideContentTypeFilter implements Filter {
#Override
public Response filter(FilterableRequestSpecification requestSpec,
FilterableResponseSpecification responseSpec,
FilterContext ctx) {
Response next = ctx.next(requestSpec, responseSpec);
return new ResponseBuilder().clone(next).setContentType(ContentType.JSON).build();
}
}
Then use it as follows:
ZipData zipdata =
given()
.filter(new OverrideContentTypeFilter())
.when()
.get(uri)
.then()
.statusCode(200)
.extract()
.as(ZipData.class);

Security Attacks possible on TokenBased Authentication?

I have designed a web application which uses very simple implementation of JWT token's to provide Authentication/Authorization.
My Implementation :
There are two types of urls's public and secure.
Public urls are to generate token with username/password.
I have added filter on secure url to check for the Authorization Header and JWT Token.
#Bean
public FilterRegistrationBean jwtFilter()
{
final FilterRegistrationBean registrationBean = new
FilterRegistrationBean();
registrationBean.setFilter(new JwtFilter());
registrationBean.addUrlPatterns("/secure/*");
return registrationBean;
}
Filter will validate the token. I haven't added expiration date yet.
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
final String authHeader = request.getHeader("authorization");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
chain.doFilter(req, res);
} else {
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
throw new ServletException("Missing or invalid Authorization header");
}
final String token = authHeader.substring(7);
try {
final Claims claims = Jwts.parser().setSigningKey(secretKey.toString).parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
} catch (final SignatureException e) {
throw new ServletException("Invalid token");
}
chain.doFilter(req, res);
}
This is providing authentication and also its is immune to CSRF.No one can create valid token without secret Key.
Are there other attacks possible on token base authentication service which i have missed?

Web API 2 use Windows Authentication for public users

How do I use Windows Authentication in WEB API for internal users who will also be on the public network? The REST API will be public facing and will need to authenticate intranet users as well as internet users. Basically, anybody not on Active Directory won't be able to access it and one more AD groups will be authorized.
The REST service at the moment has a security filter to validate token using attribute filter.
public class RestAuthorizeAttribute : AuthorizeAttribute
{
private const string SecurityToken = "token";
public override void OnAuthorization(HttpActionContext actionContext)
{
if (Authorize(actionContext))
{
return;
}
HandleUnauthorizedRequest(actionContext);
}
private bool Authorize(HttpActionContext actionContext)
{
try
{
HttpRequestMessage request = actionContext.Request;
//Extract Token from the Request. This will work for all.
// E.g \api\Facilitiles\Token\298374u23lknndsjlkfds==
// \api\Ward\123\Token\298374u23lknndsjlkfds==
string path = request.RequestUri.LocalPath;
int indexOfToken = path.IndexOf(SecurityToken) + SecurityToken.Length + 1;
string token = path.Substring(indexOfToken);
bool isValid = SecurityManager.IsTokenValid(token, IpResolver.GetIp(request),request.Headers.UserAgent.ToString());
return isValid;
}
catch (Exception ex)
{
string av = ex.Message;
return false;
}
}
}
This is then applied to specific controllers like this:
[RestAuthorize]
[RoutePrefix("api/patient")]
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class PatientDetailsController : ApiController
{
PatientDetailsRetriever _patientDetailsRetriever;
// GET: api/patient/meds/personId/{personId}/token/{token}
[Route("meds/personId/{personId}/token/{token}")]
[HttpGet]
public HttpResponseMessage GetMeds(Int64 personId, string token)
{
List<Medication> meds;
.....
The client generates the token which includes username, password and domain and among other things.
Enabling Windows Authentication in IIS (web.config) will be enough to validate local users. But how does this work when the user is outside the network and sends in the credentials?
I have found the answer on this SO post.
//create a "principal context" - e.g. your domain (could be machine, too)
using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "YOURDOMAIN"))
{
// validate the credentials
bool isValid = pc.ValidateCredentials("myuser", "mypassword");
}

How to access http session object in jersey REST service?

Hi i want to access data to anf from http session object in rest service i have googled a lot and find that #context of javax.ws.rs.core.Context gives HttpServlet object but as it is interfaec i always get it null. my code is as following
#Context
private HttpServletRequest request;
private HttpSession session = request.getSession();
#Path(value = "/listAllQuestion")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response listAllQuestion(){
int pgNo = 1;
int pgSize = 5;
IPResponse response = new IPResponse();
try {
if (session.getAttribute(IpConstants.TOPIC) != null
&& session.getAttribute(IpConstants.LEVEL) != null) {
session.removeAttribute(IpConstants.TOPIC);
session.removeAttribute(IpConstants.LEVEL);
}
session.setAttribute(IpConstants.PAGENO, pgNo);
session.setAttribute(IpConstants.PAGESIZE, pgSize);
quesList = questionService.listAllQuestion(pgNo, pgSize);
please try this:
Move your request.getSession() down inside your listAllQuestion() method, as so:
public Response listAllQuestion(){
HttpSession session = request.getSession():
I don't believe your request object will be populated outside the context of an actual request handler.

Generating random session id whenever user uses login() in web services

Am new to web services. Am trying to generate unique session id for every login that a user does, in web services.
What I thought of doing is,
Write a java file which has the login and logout method.
Generate WSDL file for it.
Then generate web service client(using Eclipse IDE), with the WSDl file which I generate.
Use the generated package(client stub) and call the methods.
Please let me know if there are any flaws in my way of implementation.
1. Java file with the needed methods
public String login(String userID, String password) {
if (userID.equalsIgnoreCase("sadmin")
&& password.equalsIgnoreCase("sadmin")) {
System.out.println("Valid user");
sid = generateUUID(userID);
} else {
System.out.println("Auth failed");
}
return sid;
}
private String generateUUID(String userID) {
UUID uuID = UUID.randomUUID();
sid = uuID.toString();
userSessionHashMap = new HashMap<String, String>();
userSessionHashMap.put(userID, sid);
return sid;
}
public void logout(String userID) {
Set<String> userIDSet = userSessionHashMap.keySet();
Iterator<String> iterator = userIDSet.iterator();
if (iterator.equals(userID)) {
userSessionHashMap.remove(userID);
}
}
2. Generated WSDL file
Developed the web service client from the wsdl.
4. Using the developed client stub.
public static void main(String[] args) throws Exception {
ClientWebServiceLogin objClientWebServiceLogin = new ClientWebServiceLogin();
objClientWebServiceLogin.invokeLogin();
}
public void invokeLogin() throws Exception {
String endpoint = "http://schemas.xmlsoap.org/wsdl/";
String username = "sadmin";
String password = "sadmin";
String targetNamespace = "http://WebServiceLogin";
try {
WebServiceLoginLocator objWebServiceLoginLocator = new WebServiceLoginLocator();
java.net.URL url = new java.net.URL(endpoint);
Iterator ports = objWebServiceLoginLocator.getPorts();
while (ports.hasNext())
System.out.println("ports Iterator size-->" + ports.next());
WebServiceLoginPortType objWebServiceLoginPortType = objWebServiceLoginLocator
.getWebServiceLoginHttpSoap11Endpoint();
String sid = objWebServiceLoginPortType.login(username, password);
System.out.println("sid--->" + sid);
} catch (Exception exception) {
System.out.println("AxisFault at creating objWebServiceLoginStub"
+ exception);
exception.printStackTrace();
}
}
On running the this file, I get the following error.
AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
faultSubcode:
faultString: java.net.ConnectException: Connection refused: connect
faultActor:
faultNode:
faultDetail:
{http://xml.apache.org/axis/}stackTrace:java.net.ConnectException: Connection refused: connect
Can anyone suggest an alternate way of handling this task ? And what could probably be the reason for this error.
Web services are supposed to be stateless, so having "login" and "logout" web service methods doesn't make much sense.
If you want to secure web services calls unfortunately you have to code security into every call. In your case, this means passing the userId and password to every method.
Or consider adding a custom handler for security. Read more about handlers here.