self registration Grails access via http (Android Client) - android

People, I have a system written in grails that makes use of Spring Security Core plugin. Now I made an Android (Java) client to access some data via HTTP. At first my code was being blocked by the spring security when i was using this code below:
DefaultHttpClient httpClient = new DefaultHttpClient();
CredentialsProvider credProvider = new BasicCredentialsProvider(); credProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), new UsernamePasswordCredentials("LOGIN", "PWD");
httpClient.setCredentialsProvider(credProvider);
it was redirecting me to the login page, but then a friend of mine configured the server and the client to use BASIC HTTP authorization, and it worked, the client sent the request, and the response was OK. But now my login page is not working, if the user is not logged in it is showed a default "basic" login/password screen to him, and not my customized login page.
if it is of any help the client code that "works" is below...
// HTTP Authentication
// Type of authentication
List<String> authPrefs = new ArrayList<String>(2);
authPrefs.add(AuthPolicy.BASIC);
httpclient.getParams().setParameter("http.auth.scheme-pref", authPrefs);
httpclient.getCredentialsProvider().setCredentials(new AuthScope(urlHost, urlPort),new UsernamePasswordCredentials("login", "pwd"));
//Preemptive mode
BasicHttpContext localcontext = new BasicHttpContext();
BasicScheme basicAuth = new BasicScheme();
localcontext.setAttribute("preemptive-auth", basicAuth);
httpContext = localcontext;
AbstractHttpMessage method = null;
method = new HttpGet(urlStr);
method.setParams(new BasicHttpParams().setParameter(urlStr, url));
// Now Execute:
HttpResponse httpResponse = httpclient.execute((HttpUriRequest) method, httpContext);

Does this help you out? This shows how you can use basic auth for some sections of your Grails web-app (where a generic window asks for username and password) and the "regular" login form for others (default web login page).
http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/single.html#9.1%20Basic%20and%20Digest%20Authentication

Related

Django: resetting password without a CSRF token

I have a Django website that manages Users. Using the built-in functionality, users can request a password reset from the website and that works great. I have implemented it according to this tutorial so I am using the built-in password reset functionality.
I have an Android app from which users should also be able to request a password reset. The problem is that I do not have a CSRF token in the application, and the the built-in password_reset method has the #csrf_protect decorator. This means that I cannot access it without a CSRF token and I also can't modify it with the #csrf_exempt decorator.
So the next idea is to create a function, which generates a CSRF token, stores it in the request and redirects to the correct URL which sends the reset email. The problem is that according to this, django does not allow to pass POST parameters further in a redirect.
Therefore my question is how can I request a password reset in Django without a CSRF token? Alternatively, what is the correct way to request this from an application?
I found a solution myself. Please feel free to post any alternative solutions. One that doesn't require two separate requests would be particularly great.
If you look at the password_reset method, you can see that it only tries to process the request as a reset request if the request method is POST. Otherwise it just returns a TemplateResponse containing a form. This also contains the CSRF token as a cookie.
So first, I send a GET request to http://myaddress.com/user/password/reset/ and extract the CSRF cookie from the response. Then I send a POST request containing the cookie, the email address and 2 headers (see below).
This is the code I've implemented to achieve this from Android (trimmed):
String url = "http://myaddress.com/user/password/reset/";
GET Request:
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
CookieStore cookieStore = new BasicCookieStore();
HttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpResponse httpResponse = httpClient.execute(httpGet, localContext);
Cookie csrfCookie = null;
for (Cookie cookie : cookieStore.getCookies()) {
if (cookie.getName() == "csrftoken") {
csrfCookie = cookie;
break;
}
}
if (csrfCookie == null) {
throw new NullPointerException("CSRF cookie not found!");
}
return csrfCookie;
Note that you want the CookieStore from org.apache.http.client.
POST Request:
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
// Prepare the cookie store to receive cookies.
CookieStore cookieStore = new BasicCookieStore();
cookieStore.addCookie(csrfCookie);
httpPost.setHeader("Referer", url);
httpPost.setHeader("X-CSRFToken", csrfCookie.getValue());
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addTextBody("email", emailAddressToReset);
httpPost.setEntity(builder.build());
HttpResponse httpResponse = httpClient.execute(httpPost, localContext);
if (httpResponse.getStatusLine().getStatusCode() != 200) {
throw new Exception("Could not reset password!");
}
Toast.makeText(context, "Password reset requested! Please check your email inbox!", Toast.LENGTH_LONG).show();

how can we tell the host that we are requesting a webpage from android device

Actually I'm using HttpClient() and HttpPost() methods for downloading the html source
here is the code for downloading:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(_url);
try {
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
responseBody = EntityUtils.toString(response.getEntity());
}
If I execute the above code some sites like www.google.com (which will give user agent specific code (HTML code)), not giving whole information suitable for android. So I can tell the host that I'm requesting webpage from android device.

Using HttpGet returning complete HTML code

I am trying to invoke a private web-service in which there's one link I've to access using GET method. While using the direct URL on browser (needs to login first), I get the data in JSON format. The URL I am invoking is like this
http://www.example.com/trip/details/860720?format=json
The url is working fine, but when I invoke this using HttpGet, I am getting the HTML coding of the webpage, instead of the JSON String. The code I am using is as follows:
private String runURL(String src,int id) { //src="http://www.example.com/trip/details/"
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(src);
String responseBody="";
BasicHttpParams params=new BasicHttpParams();
params.setParameter("domain", token); //The access token I am getting after the Login
params.setParameter("format", "json");
params.setParameter("id", id);
try {
httpget.setParams(params);
HttpResponse response = httpclient.execute(httpget);
responseBody = EntityUtils.toString(response.getEntity());
Log.d("runURL", "response " + responseBody); //prints the complete HTML code of the web-page
} catch (Exception e) {
e.printStackTrace();
}
return responseBody;
}
Can you tell me what am I doing wrong here??
Try specify Accept & Content-Type in you http header:
httpget.setHeader("Accept", "application/json"); // or application/jsonrequest
httpget.setHeader("Content-Type", "application/json");
Note that you can use tools like wireshark capture and analyse the income and outcome http package, and figure out the exact style of the http header that returns your json response from a standard browser.
Update:
You mentioned need login first when using browser, the html content returned is probably the login page (if use basic authentication type, it returns a short html response with status code 401, so a modern browser knows how to handle, more specifically, pop up login prompt to user), so the first try would be checking the status code of your http response:
int responseStatusCode = response.getStatusLine().getStatusCode();
Depend on what kind of authentication type you use, you probably need specify login credentials in your http request as well, something like this (if it is a basic authentication):
httpClient.getCredentialsProvider().setCredentials(
new AuthScope("http://www.example.com/trip/details/860720?format=json", 80),
new UsernamePasswordCredentials("username", "password");

Server not Recognising Cookie From Android Phone

I am trying to connect to a drupal server. I have been able to do this in the past but the drupal developers now require me to add another cookie. The server does not register the cookie that I am trying to send below. Can anybody see why?
public static void maybeCreateHttpClient() {
if (mHttpClient == null) {
mHttpClient = new DefaultHttpClient();
final HttpParams params = mHttpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params,
REGISTRATION_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, REGISTRATION_TIMEOUT);
ConnManagerParams.setTimeout(params, REGISTRATION_TIMEOUT);
BasicCookieStore cookieStore = new BasicCookieStore();
ClientCookie cookie = new BasicClientCookie("aml", key);
cookieStore.addCookie(cookie);
localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
}
}
It turns out that, I didn't need to use cookie, cookstore or httpcontent. As far as I can understand these are mainly used to managed cookies coming from the server.
I managed to solve my problem by setting a header like so
String key = "whatever";
post.addHeader("Cookie", "aml=" + key);
This can be used on httppost, httpget or httput.
That took me a few days for such a simple solution. I hope it helps somebody else out
Oh, well if you're looking for why the cookies weren't added, you weren't getting or adding the cookie store from the http client. You should get the cookie store from the client, add your cookies, and then execute your request.

Android: Unable to login to a web session and parse XML data using DOM on the same login session

Android Development: I'm needing to log into a web session using POST, then make another request of which I parse XML to get Lat/Long, then submit this to a google maps overlay.
My issue is I'm able to log into my system, but when I submit a command to parse XML, it is acting like a completely new session and I basically get an 'incorrect login' reply from the server.
Does anyone have some simple steps to perform this...and to keep a session open for as many commands as I need? I'm not actually SURE I'm using a session cookie, but believe this is the case.
Some example code may be:
try {
URI loginUri = new URI("http://www.mywebsite.com/ExternalLogin.jsp?user=lee&pwd=bluedog");
URI xmlUri = new URI("http://www.mywebsite.com/getXMLInfo.xml");
// Prepares the request.
HttpClient httpClient = new DefaultHttpClient();
HttpGet loginHttpGet = new HttpGet();
loginHttpGet.setURI(loginUri);
HttpGet xmlHttpGet = new HttpGet();
xmlHttpGet.setURI(xmlUri);
// Sends the request and read the response
HttpResponse loginResponse = httpClient.execute(loginHttpGet);
InputStream loginInputStream = loginResponse.getEntity().getContent();
HttpResponse xmlResponse = httpClient.execute(xmlHttpGet);
InputStream xmlInputStream = xmlResponse.getEntity().getContent();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(xmlInputStream.toString()));
doc.getDocumentElement();
// Continue using DOM to parse my XML data
}
You don't indicate your how our "web session" is being maintained. I am going to guess it is via a session cookie. If so, use HttpClient and keep using the same HttpClient object for both requests. The session cookies will be handled automatically.

Categories

Resources