Android Java Volley Persisting the Session in Classic ASP - java

I'm writing a simple app which logs onto my webservice and then downloads some information via SQL about the logged in user.
Currently I have a dependency on Google's Volley and can readily send off volleys, read the response, etc. However, the problem comes when ASP (backend) is creating a new session on each request, thereby clearing any set session variables.
I've tried to read the response back from the server to get the cookie, and then attach that as a header on any subsequent volley, but it's not working as expected. I need to figure out why my sessions aren't persisting.
INIT
String sSessionID = "";
My Volley call
String urlLoginAttempt = SERVER_ADDRESS + PAGE_LOGIN + "?u="+username+"&p="+pw;
Response.Listener responseListener = new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(ctx, "DEBUG\nVolley Session ID : " + sSessionID, Toast.LENGTH_SHORT).show();
}
};
StringRequest stringRequest = new StringRequest(Request.Method.POST, urlWithParams, responseListener, this.errorListener) {
//Add an extra cookie value header into the request, if cookie variable has been set
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
if (!sSessionID.equalsIgnoreCase("")) {
params.put("Cookie", sSessionID);
}
return params;
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
//Volley can automatically get the session ID
sSessionID = parseCookie(response.headers.get("Set-Cookie"));
return super.parseNetworkResponse(response);
}
public String parseCookie(String cookie) {
String[] splitCookie = cookie.split(";");
String[] splitSessionId = splitCookie[0].split("=");
String sCookie = splitSessionId[1];
return sCookie;
}
};
// Add the request to the RequestQueue.
netQ.add(stringRequest);
On first call, sSessionID is empty.
As the first response is received (a login attempt), the "set-Cookie" header is stripped, parsed, and saved into the local variable sSessionID
The actual response from the ASP backend is currently "1" or "0", depending on whether the correct username/password has been sent to the server. This works correctly. When the response is "1", the backend also sets some session variables
When I try and re-login, I step into the code and see that the session id (cookie) has been changed, and no set session variables exist. This happens even though all subsequent requests I add a "Cookie" header with that same sSessionID to try and persist the session.
An example sSessionID value would be the header value HTTP_COOKIE: ASPSESSIONIDXXXXXXX=IAOPCEODJPBJGJXXXXXXX; stripped down to IAOPCEODJPBJGJXXXXXXXX
Login.ASP Page
<%
//Attempt to set any session variable to begin a new session
session("userid")=-1
username=ucase(request.querystring("u"))
pw=request.querystring("p")
//for testing only:
if username="J" AND pw="pass" then
session("userid")="188473"
session("name")="Jammo"
...
response.write("1")
else
session("userid")=-1
reponse.write("0")
end if
%>
EDIT
A little more overview of my environment. On my webserver I have login.asp and getdata.asp. If I send a volley onto getdata then the ASP page will try and see if the user is logged in my checking the session var session("userid"). If there is no value set, I assume there is no user logged in. The page will return a "0" and the app will switch the user back to my login tab. If there IS a value set in session("userid") then it will return data about the current user name (JSON format).
Session variables on ASP seem to be the sensible way to do this... As Volleys are stateless, in order to do this I seem to have to send in a custom header with the request to show the session variable ("Cookie" header). However, this isn't working as the returned session variable still changes with each volley response

Related

How to pick values from a redirected_url using Springboot

I want to be able to fetch a param from the redirect url whenever it is automated. I am having difficulties doing this as I am getting a bad request after I created another endpoint to effect this.
I have an endpoint that works fine. The endpoint is a get method. Loading the endpoint takes a user to a page where they need to provide some necessary details. Once these details have been verified, the user is redirected to my redirecr_uri. The redirect_uri now contains important information like session_id, code, etc. The most important thing I need is the code. I need to pass the code into yet another endpoint which will return an access token.
I have manually done this process and it works but I want it to be done automatically because I can't keep doing that when I push the code to staging or production.
Here is the endpoint that redirects as well as the method.
#GetMapping("/get-token")
public RedirectView getBvn() throws UnirestException {
return nibss.getAccessToken();
}
This is the method that the controller calls
public RedirectView getAccessToken() throws UnirestException {
String url = "https://idsandbox.nibss-plc.com.ng/oxauth/authorize.htm?scope=profile&acr_values=otp&response" +
"_type=code&redirect_uri=https://www.accionmfb.com/&client_id=0915cd00-67f2-4768-99ac-1b2ff9f1da2e";
RedirectView redirectView = new RedirectView();
redirectView.setUrl(url);
return redirectView;
}
When the user provides the right information they are redirected to something like this
https://www.accionmfb.com/?code=9ad91f13-4698-4030-8a8f-a857e6a9907e&acr_values=otp&scope=profile&session_state=fa525cabc5b62854c73315d0322fd830c12a5941b89fd8e6e518da369e386572.b78a3d21-e98e-4e9a-8d60-afca779d9fad&sid=fd60ab92-ef37-4a5b-99b9-f8f52321985d
It is important to state that this 3rd party API I am trying to consume uses oath2.0 client authentication.
I created this endpoint to get the code from the redirected_uri
#GetMapping("/redirect-url")
public void handleRedirect(#RequestParam("code") String code) throws UnirestException {
if(Objects.nonNull(code) || !code.isEmpty()){
nibss.getToken(code);
log.info("Code is not being passed {}", code);
} else {
log.info("Code is not being passed {}", code);
}
}
public String getToken(String code) throws UnirestException {
log.info("This is the code here oooooooooo {}", code);
String url = "https://idsandbox.nibss-plc.com.ng/oxauth/restv1/token";
String parameters = "client_id=0915cd00-67f2-4768-99ac-1b2ff9f1da2e&code="+code+"&redirect_uri=https://www.accionmfb.com/&grant_type=authorization_code";
HttpResponse<String> apiResponse = Unirest.post(url)
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Authorization", "Basic MDkxNWNkMDAtNjdmMi00NzY4LTk5YWMtMWIyZmY5ZjFkYTJlOlRVRnEwcGFBQXRzbzBZOEcxMkl2WFZHUmx6WG5zaERiaGt1dzI1YUM=")
.body(parameters)
.asString();
//JSONObject apiJson = apiResponse.getBody().getObject();
//return apiJson.getString("access_token");
JSONObject json = new JSONObject(apiResponse.getBody());
String accessToken = json.getString("access_token");
log.info(accessToken);
return accessToken;
}
But this is not working, I get 400 whenever I hit the second endpoint. What am I doing wrong?
The redirect_uri that you are passing to the OAuth server is https://www.accionmfb.com which does not include the path /redirect-url so the redirect never hits your method.
Either register and pass a callback uri like redirect_uri=https://www.accionmfb.com/redirect-url
Or change #GetMapping("/redirect-url") to #GetMapping("/")

How to delete a cookie from backend upon an error

Currently setting up http only cookie in a Spring boot project via configurations as follows.
This cookie is getting set correctly when ever I call following endpoint.
#Bean
public CookieSerializer defaultCookieSerializer() {
DefaultCookieSerializer cookie = new DefaultCookieSerializer();
cookie.setDomainNamePattern(".*");
cookie.setCookieName("my_cookie");
cookie.setUseSecureCookie(true);
cookie.setUseHttpOnlyCookie(true);
cookie.setCookieMaxAge(1200);
return cookie;
}
As can see, the cookie called my_cookie is being set for 2 mins.
In my controller within same project, I have the following controller method.
In the event I enter the error block, I wish to delete the cookie called my_cookie. How can I do that?
This is the closest question I found for this but is not the same case considering I set it via configurations.
https://stackoverflow.com/questions/9821919/delete-cookie-from-a-servlet-response
#PostMapping(value = "/endpoint")
public List CustomResponse(
#RequestBody Request request,
) throws Exception {
CustomResponse response = null;
if (otherCookie != null) {
CustomResponse response = // perform some other rest request and get value from there
}
if (response == null) {
// I want to delete the cookie named `my_cookie` at this stage.
throw new CustomException('name');
}
return response;
}
To delete a cookie, set the Max-Age directive to 0 and unset its value. You must also pass the same other cookie properties you used to set it. Don't set the Max-Age directive value to -1. Otherwise, it will be treated as a session cookie by the browser.
// create a cookie
Cookie cookie = new Cookie("username", null);
cookie.setMaxAge(0);
cookie.setSecure(true);
cookie.setHttpOnly(true);
cookie.setPath("/");
//add cookie to response
response.addCookie(cookie);
For more, refer to the post by Dzone:
https://dzone.com/articles/how-to-use-cookies-in-spring-boot

Error while requesting an access token. No accessTokenResponse object recieved, maybe a non HTTP 200 received?

I was following this tutorial: https://developers.docusign.com/esign-rest-api/code-examples/config-and-auth
(I used java)
In the third step I dont know how to get the code that is sent back form DocuSign as query param in the redirect uri:
// Java request auth token
**String code = "{ENTER_AUTH_CODE_FROM_PREVIOUS_STEP}";**
// assign it to the token endpoint
apiClient.getTokenEndPoint().setCode(code);
// optionally register to get notified when a new token arrives
apiClient.registerAccessTokenListener(new AccessTokenListener() {
#Override
public void notify(BasicOAuthToken token) {
System.out.println("Got a fresh token: " + token.getAccessToken());
}
});
// following call exchanges the authorization code for an access code and updates
// the `Authorization: bearer <token>` header on the api client
apiClient.updateAccessToken();
I get an error saying the requested access token is null. Below is the error:
Error while requesting an access token. No accessTokenResponse object received, maybe a non HTTP 200 received?
Has anybody ever got the same one or could maybe someone tell me how to fix it.
I ran below code and its working fine for me, after getting code from the previous step in the URL:
public static void main(String[] args) {
String IntegratorKey = "[Your_Integrator_Key]";
String ClientSecret = "[Your_Secret_Key]";
String RedirectURI = "https://www.getpostman.com/oauth2/callback";//This REDIRECT_URI should match whats configured with IntegratorKey in your Sandbox account
String AuthServerUrl = "https://account-d.docusign.com";
String RestApiUrl = "https://demo.docusign.net/restapi";
ApiClient apiClient = new ApiClient(AuthServerUrl, "docusignAccessCode", IntegratorKey, ClientSecret);
apiClient.setBasePath(RestApiUrl);
apiClient.configureAuthorizationFlow(IntegratorKey, ClientSecret, RedirectURI);
Configuration.setDefaultApiClient(apiClient);
String code = "{ENTER_AUTH_CODE_FROM_PREVIOUS_STEP}";
apiClient.getTokenEndPoint().setCode(code);
apiClient.registerAccessTokenListener(new AccessTokenListener() {
#Override
public void notify(BasicOAuthToken token) {
System.out.println("Got a fresh token: " + token.getAccessToken());
}
});
apiClient.updateAccessToken();
}
To get the code returned by DocuSign from browser, you need to have a WEBApp to which DocuSign will redirect the browser, this same callback URL should be configured in your DS Sandbox's REDIRECT_URI, for instance if you WEBApp callback URL is http://locahost:8080/docusignapp/callback, then this should be added in REDIRECT_URI in IntegratorKey and same needs to be added when calling DS URL to authenticate a user. Once DS authenticates the user, it will redirect the browser to your APP url. On hitting your WEBApp then you need to read the URL and strip off the code part using Javascript, then run the step2 to get the access Token. A sample JS code to strip the code part is:
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
var authCode = vars["code"];
In the example which you share they did it using Standalone code, where you are manually copying the code part from the URL after authentication and running the step2.

How to set cookies in Spark Java being deployed in Apache Tomcat

Recently I started using Spark Java Framework (2.7.2) to create a lightweight web application. One of its requirements is that the application must be deployed to an Apache Tomcat Server 8.5.
I've managed to set things going, but I have not been able to set any custom cookie.
I have used the following method but none worked.
response.cookie("my_cookie", "value");
response.cookie("/path", "my_cookie", "value", -1, false, true);
It seems like tomcat is setting correctly the JSESSIONID cookie but I have no control over this cookie generation and I would like to generate a random and unique cookie, in order to be used for user authorization.
EDIT:
The control flow for setting the cookie is this
// In the main application
before("/*", AccessController.setSession);
// Method for setting an existing session
public static Filter setSession = (Request request, Response response) -> {
// If the user is not set in the session
if (!SessionUtil.hasSession(request)) {
// Obtain the cookie session ID
String sessionId = SessionUtil.getCookie(request);
System.out.println(sessionId);
// Obtain the user according to the session ID
User user = app.getUserFromSession(sessionId);
System.out.println(user != null);
// if does exists we set the session
if (user != null)
SessionUtil.setSession(request, user);
}
};
// Methods for the session
public static boolean hasSession(Request request) {
if (request.session().attribute("user") == null)
return false;
return true;
}
public static String getCookie(Request request) {
return request.cookie(COOKIE_NAME);
}
public static void setSession(Request request, User user) {
request.session().attribute("user", user);
}
This is called when a login is succesfull. Cookie is stored in the user database persisting sessions
public static void setSession(Response response, String cookie) {
response.cookie(COOKIE_NAME, cookie);
}

cant get correct session id to login to spring security with retrofit

I'm trying to create automated, end to end, tests to my webapp by making rest calls (using retrofit). our rest calls are protected with spring security, so i have to login first.
To my best understanding, i need to call /j_spring_security_check with user/password, get the returned "Set-cookie" response header and set it as a "Cookie" request header on each rest call i perform.
It seems like my call to spring login "page" is successful as we have implemented an ApplicationListener which logs each successful login attempt,
however, the returned response from the call to j_spring_security_check has a status 200 (should be 302 as the apps redirects after successful login) and the body of the response is the login page itself.
What am i doing wrong?
the login retrofit interface:
#FormUrlEncoded
#POST("/j_spring_security_check")
Response basicLogin(#Field("user") String user, #Field("password") String pwd);
the code to call spring's login:
public static void login(String user, String pwd) {
PortalLoginService loginService = PortalRestAdapter.getInstance().createLoginService();
Response response = loginService.basicLogin(user, pwd);
String setCookieHeader = getSetCookieHeader(response.getHeaders());
AuthCookieInterceptor.getInstance().setSessionId(setCookieHeader);
}
private static String getSetCookieHeader(List<Header> headers) {
for (Header header : headers) {
if (SET_COOKIE_HEADER_NAME.equals(header.getName())) {
return header.getValue();
}
}
return null;
}
code of AuthCookieInterceptor intercpet method:
#Override
public void intercept(RequestFacade requestFacade) {
if (sessionId != null) {
requestFacade.addHeader("Cookie", sessionId);
}
}
the rest adapter init:
restAdapter = new RestAdapter.Builder()
.setRequestInterceptor(AuthCookieInterceptor.getInstance())
.setEndpoint(PORTAL_URL)
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
so basically I'm making a call to login, and setting the returned session id from the login response on each request i make after (using request interceptor)
Thanks a lot
You need to change the name of the parameters passed, j_spring_security_check is expecting j_username and j_password instead of your
Response basicLogin(#Field("user") String user, #Field("password") String pwd);
Also, because in the case of this call, the spring framework is returning us a html response (keep in mind that we are doing a POST to servlet), we need to set our converter, so you need to do something like this:
SimpleXMLConverter converter = new SimpleXMLConverter();
RestAdapter adapter = builder.setLogLevel(RestAdapter.LogLevel.FULL).setConverter(converter).build();
then a simple call like this one:
Response response = LoginClient.getService().login("john", "john1");
and from the response object, you can get any information you could need
I have solved this puzzle.
Frist of all to authorize user you need to replace "user" with "username"
#FormUrlEncoded
#POST("/login")
Response autorizeMethod(#Field("username") String user, #Field("password") String pwd);
then disable auto redirection in retrofit
val client=OkHttpClient.Builder().followRedirects(false).build()
Retrofit.Builder()
.baseUrl("http://localhost:8080")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()

Categories