pass authentication parameter in webservice - json

I am building a webservice server side. In my webservice, every client needs to pass their authentication parameter, via POST method in json format, for every request they make. Is passing parameter via post a good practice?
A guy told me, I should always use GET method to retrieve data; POST should be used for insertion only. If this is so, how am I going to pass the authentication param? One could be through URL and the other through header value. Which way should I use?

try to implement this web service. This web service permits to pass their authentication parameter through header value.
#WebService(serviceName="authentication")
public class WSAuthentication {
String name = null;
String password = null;
public WSAuthentication() {
super();
}
public WSAuthentication(String name, String password) {
this.name = name;
this.password = password;
}
private static String getData(WSAuthentication sec) {
System.out.println("********************* AUTHENTICATION ********************" + "\n" +
"**********USER: " + sec.name + "\n" +
"******PASSWORD: " + sec.password + "\n" +
"******************************** AUTHENTICATION ****************************");
return sec.name + " -- " + sec.password;
}
#WebMethod(operationName="security", action="authenticate")
#WebResult(name="answer")
public String security(#WebParam(header=true, mode=Mode.IN, name="user") String user, #WebParam(header=true, mode=Mode.IN, name="password") String password) {
WSAuthentication secure = new WSAuthentication(user, password);
return getData(secure);
}
}
And I use POST method for response. I hope help you.

Related

How to set JWT type in JWT Header

Not able to set the JWT token typ in token header.
This is for making secure API's which i have already developed in JAX-RS. Basically i have generating a token by Jwts.builder() method, and in return i am getting token in APPLICATION_JSON, ant i paste this token at https://jwt.io/ Debugger. So i got to know that there is no token type specified token header,there is only {
"alg": "HS512"
}
Maybe this could be a reason that i cannot access secured API's. When i try to access secured API's then i got "Signed Claims JWSs are not supported" exception.
AuthenticationService.java
private String issueToken(String login, String password) {
LocalDateTime now = LocalDateTime.now().plusMinutes(10L);
Instant instant = now.atZone(ZoneId.systemDefault()).toInstant();
Date jwtExpiry = Date.from(instant);
String jwtToken = Jwts.builder().setSubject(login).setIssuer("XYZ").setIssuedAt(new Date())
.setExpiration(jwtExpiry).signWith(SignatureAlgorithm.HS512, "secretKey").compact();
return jwtToken;
}
public class JWTTokenNeededFilter implements ContainerRequestFilter
{
public static final Logger logger = Logger.getLogger(JWTTokenNeededFilter.class);
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String token = requestContext.getHeaderString("userToken");
if (token == null) {
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
try {
Jwts.parser().setSigningKey("secretKey").parseClaimsJwt(token);
logger.info("Valid Token " + token);
} catch (ExpiredJwtException expiredJwtException) {
logger.info("Token Expires " + expiredJwtException);
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
catch (Exception exception) {
logger.info("Exceptioin " + exception);
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
}
}
I am expecting token header like this
{
"alg": "HS512",
"typ": "JWT"
}
You can set the header just using the setHeaderParam("typ","JWT") jwt builder method.
https://github.com/jwtk/jjwt#header-parameters
String token = Jwts.builder()
.setHeaderParam("typ","JWT")
.setSubject(user.getUserId().toString())
.claim("Roles",authResult.getAuthorities())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis()+EXPIRATION_TIME))
.signWith(Keys.hmacShaKeyFor(key))
.compact();
You can set using header as explained here : https://github.com/jwtk/jjwt/issues/174
Header header = Jwts.header();
header.setType("JWT");
Then set header to builder (I haven't compiled the code)
private String issueToken(String login, String password) {
LocalDateTime now = LocalDateTime.now().plusMinutes(10L);
Instant instant = now.atZone(ZoneId.systemDefault()).toInstant();
Date jwtExpiry = Date.from(instant);
Header header = Jwts.header();
header.setType("JWT");
//set additional headers
String jwtToken =
Jwts.builder().setHeader((Map<String, Object>)
header).setSubject(login).setIssuer("XYZ").setIssuedAt(new
Date())
.setExpiration(jwtExpiry).signWith(SignatureAlgorithm.HS512,
"secretKey").compact();
return jwtToken;
}
you can use Header.JWT_TYPE static field in Header interface. This is more cleanable and avoid boilerplate code: For example:
private static String generateToken() {
return Jwts.builder()
.signWith(SignatureAlgorithm.HS256, secretKey)
.setHeaderParam("typ", Header.JWT_TYPE)
.compact();
}
and output which you want:
{
"typ": "JWT",
"alg": "HS256"
}

Loopj Put and Post with basic auth return null response with no error

This is an attempt to use Loopj for a Synchronous put and post call from a HTTP utility class. The code uses a syncrhonous client as it’s used inside an AsyncTask and some UI interactions depend heavily on the json response so the AsyncTask is managing making the call asynchronously.
All the get calls from the HTTP utility class are working successfully. The post and put do not and they both appear to have exactly the same problem.
The json string is created using Gson. I’ve tested the json output from the application directly in Postman and it posts exactly as expected to the API, so it appears to be well formed and behaves totally as expected without any errors.
Both the put and post calls are constructed without throwing an error. Basic authorization is being added (as shown on the client instance). The SyncHTTPClient put method is called using a null context parameter. I did a bit of research and found a single post where this was being done successfully.
https://github.com/loopj/android-async-http/issues/1139
The put call fires but doesn’t enter either the overridden methods of the handler. It just returns null. I've included a portion of the working class to view:
public void executePutSave(String name, String pass, String jsonBody) {
client.setBasicAuth(name, pass);
executeLoopJPutCall("/api/Save", jsonBody);
}
public void executeLoopJPutCall(String relativeUrl, String jsonBody) {
String url = getAbsoluteUrl(relativeUrl);
StringEntity entity = new StringEntity(jsonBody, "UTF-8");
jsonResponse = null;
client.put(null, url, entity, "application/json", new JsonHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
super.onSuccess(statusCode, headers, response);
jsonResponse = response.toString();
Log.i(TAG, "onSuccess: " + jsonResponse);
}
#Override
public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) {
super.onFailure(statusCode, headers, throwable, errorResponse);
jsonResponse = errorResponse.toString();
Log.e(TAG, "onFailure: " + statusCode + errorResponse );
}
}
);
}
So, apparently the header must be added explicitly when using the above code to Post or Put json to the API. Once I changed the header authentication line from this:
client.setBasicAuth(name, pass);
To this:
String userpass = name + ":" + pass;
String encoded = new String(Base64.encode(userpass.getBytes(),Base64.NO_WRAP));
client.addHeader("Authorization", "Basic "+encoded);
...everything worked as expected.
I found the information on this blog: https://github.com/loopj/android-async-http/issues/113
Passing a null context worked, too.

How to run JUnit testing on Firebase Java with authentication?

I am currently using Firebase Authentication in my mobile app. The back end is a Spring boot application. The REST APIs on the back end relies on a token generated from Firebase Authentication to retrieve the Firebase UID (verifyIDToken method) of a user to perform further functions.
Currently, I notice that in Firebase Java API (server-based), there is no way of generating a token for a user, thus there is no easy way for me to do JUnit testing on the server that relies on user authentication. Anyone has clues on how to do so?
This is the sample code that does not work:
#RequestMapping(value = "/api/subscribeChannel/{channelid}", method = RequestMethod.GET, produces = "application/json")
public DeferredResult<Object> subscribeChannel(#PathVariable Long channelid,#RequestHeader(value=FIREBASETOKEN, required = true) String idToken) {
DeferredResult<Object> result = new DeferredResult<Object>(DEFERREDTIMEOUT);
// test it out with a locally generated token
idToken = FirebaseAuth.getInstance().createCustomToken("valid Uid");
Task<FirebaseToken> task = FirebaseAuth.getInstance().verifyIdToken(idToken)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
String uid = decodedToken.getUid();
logger.info("Subscribe channel on success");
// do something
ret.setStatus("success");
ret.setMessage("channel id " + channelid + " subscribed");
result.setResult(ret);
} else {
result.setErrorResult(retStatus.getMessage());
}
}
}) .addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception arg0) {
Exception te = new TokenNotFoundException(idToken);
logger.error("Token Not Found for " + idToken);
result.setErrorResult(te);
}
});
return result;
}
The custom token you get is different from the ID token that you use to log on. To get an id token from a custom token, do this:
private static final String ID_TOOLKIT_URL =
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken";
private static final JsonFactory jsonFactory = Utils.getDefaultJsonFactory();
private static final HttpTransport transport = Utils.getDefaultTransport();
private static final String FIREBASE_API_KEY = "<your api key here>";
private String signInWithCustomToken(String customToken) throws IOException {
GenericUrl url = new GenericUrl(ID_TOOLKIT_URL + "?key="
+ FIREBASE_API_KEY);
Map<String, Object> content = ImmutableMap.<String, Object>of(
"token", customToken, "returnSecureToken", true);
HttpRequest request = transport.createRequestFactory().buildPostRequest(url,
new JsonHttpContent(jsonFactory, content));
request.setParser(new JsonObjectParser(jsonFactory));
com.google.api.client.http.HttpResponse response = request.execute();
try {
GenericJson json = response.parseAs(GenericJson.class);
return json.get("idToken").toString();
} finally {
response.disconnect();
}
}
The Java API to generate custom tokens is documented under Create custom tokens using the Firebase SDK.
From there:
String uid = "some-uid";
String customToken = FirebaseAuth.getInstance().createCustomToken(uid);

CDI - Java EE Servlet saving variables to a managed bean

I have a Java EE class that currently reads info from a form and prints it out.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Response extends HttpServlet
{
String date = "0";
public void init() throws ServletException
{
//Get Election Date from xml
String initial = getInitParameter("electionDate");
date = initial;
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException
{
//Get values from form
PrintWriter out = response.getWriter();
String firstName=request.getParameter("firstname");
String lastName=request.getParameter("lastname");
String address=request.getParameter("address");
String city=request.getParameter("city");
String state=request.getParameter("state");
String zip=request.getParameter("zip");
String phone = request.getParameter("phone");
String affil=request.getParameter("affil");
//Print Summary of Voter Registration
out.println("<html>");
out.println("<head><title>Registration Summary</title></head>");
out.println("<body>");
out.println("<p>Registration Summmary</p>");
out.println("<p>First Name: " + firstName + "</p>");
out.println("<p>Last Name: " + lastName + "</p>");
out.println("<p>Address : " + address + "</p>");
out.println("<p>City : " + city + "</p>");
out.println("<p>State : " + state + "</p>");
out.println("<p>Zip: " + zip + "</p>");
out.println("<p>Phone Number: " + phone + "</p>");
out.println("<p>Affiliation: " + affil + "</p>");
out.println("<p>Next Election Date: " + date + "</p></p>");
out.println("<p>Is the above information correct?</p>");
out.println("<button>Yes</button>");
out.println("<button>No</button>");
out.println("</body></html>");
out.close();
}
}
I want to get the values (firstName, lastName, etc.) from this Java servlet and inject to a bean.
Then when this file calls another servlet I want the values from the bean to be available in that servlet.
I just want to know how to store the variables I created above into a managed bean and then have the other servlet reference and retrieve the variables in that bean.
I have beans.xml, web.xml, pom.xml (I'm using Maven) files set up already.
You cannot simply inject Strings, so you will have to use a qualifier (the simplest one is #Named, see if that is sufficient).
In your servlet, say
#Produces
#Named("foo")
String lastName;
...
void doPost() {
lastName = getParameter(...);
}
and in the target bean, use
#Inject
#Named("foo")
String lastName;
Since you are in a Request-Scope, keep in mind that injecting request-scoped values into longer living instances (EJBs for example) might lead to unpredictable behavior. I seriously doubt that your approach will make you happy. Perhaps you could tell us more about what you are trying to do?

JPA difference Windows / Unix System?

For development purposes i'm using a windows environment (Eclipse / Jboss)
There i have a userDAO, that offers the method to rerieve a UserEntity by first- and lastname. This Query runs well on the dev environment. However on the Unix-Environment, i get a javax.persistence.NoResultException: No entity found for query Exception.
Situation in Detail:
A REST-Service is beeing called, containing many Data, along with a firstname and lastname. this parameters needs to be used to obtain the actuall userEntity. (It fails for ANY user on Unix.)
So, the rest service is doing this:
#Consumes("application/json")
#Produces("application/json")
public String create(String plaindata) {
JSONObject data = new JSONObject(plaindata);
String ownerFirstname = data.getString("userFirstname"); //Yes userX, not ownerX
String ownerLastname = data.getString("userLastname");
UserEntity owner = null;
try {
owner = userDataService.getUserDetailsByName(ownerFirstname, ownerLastname);
} catch (Exception e) {
throw new Exception("Found zero possible users for the given name '" + ownerFirstname + " " + ownerLastname
+ "'. Cannot invoke process.", e);
}
...
}
The userDataService looks (stripped) like this:
private static String GET_USER_BY_FIRSTNAME_LASTNAME_QUERY = "SELECT * FROM " + DBConstants.USER_TABLE_NAME
+ " user WHERE user.FIRST_NAME = :firstnameValue AND user.LAST_NAME = :lastnameValue";
public UserEntity getUserDetailsByName(String firstname, String lastname) {
Query query = em.createNativeQuery(GET_USER_BY_FIRSTNAME_LASTNAME_QUERY, UserEntity.class);
query.setParameter("firstnameValue", firstname);
query.setParameter("lastnameValue", lastname);
UserEntity u = (UserEntity) query.getSingleResult();
return u;
}
DBConstants contains the table name like:
public static final String DATATABLE_PREFIX = "pre_";
public static final String USER_TABLE_NAME = DATATABLE_PREFIX+"user_entity";
Column Names in mySQL are Capitalized, so everything seems right.
this works on a Windows Environment, but NOT in the Unix Environment :(
String ownerFirstname = data.getString("userFirstname").trim();
String ownerLastname = data.getString("userLastname").trim();
And it works... Strange thing - what could be the difference between windows and unix towards this issue? (The Exception logged absolutely NO Whitespace)