Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android webview with https connection and basic auth. How to get this working?

I have researched and researched and researched this until I've gone grey and bald. How on earth do I get a webview to work for a site that needs http basic authentication over an https connection on api level 8+

I have the following code

    String email = Util.getEmail(this);
    String pwd = Util.getPassword(this);
    webview.getSettings().setJavaScriptEnabled(true);
    webview.setHttpAuthUsernamePassword(Config.SERVER_BASE_URL, "Application", email, pwd);

//      webview.setWebViewClient(new MobileWebViewClient(this));
    webview.loadUrl(url);

As you can see I did have a web view client (Now commented out) that overrides the onReceivedHttpAuthRequest method which looks like this

@Override
public void onReceivedHttpAuthRequest (WebView view, HttpAuthHandler handler, String host, String realm){
    String email = Util.getEmail(wvContext);
    String pwd = Util.getPassword(wvContext);
    if(!pwd.equalsIgnoreCase("-1") && !pwd.equalsIgnoreCase("-1")){
       handler.proceed(email, pwd);
    }
}

This was used without the webview.setHttpAuthUsernamePassword and works fine except that it means 2 requests are issued to the website - The first gets a 401 and then the client kicks in with the authorisation stuff This is fine for a small amount of website traffic but halving the amount of traffic (currently averaging 49 requests p/m) is the name of the game right now!

I read that I can pre-emptively supply the credentials by using

webview.setHttpAuthUsernamePassword(Config.SERVER_BASE_URL, "Application", email, pwd);

However this just results in Http Basic: Access denied errors The server base url constant is the domain name for the site i.e. https://example.com (without the page) the actual url is https://example.com/some_pages. It makes no difference whether I use the full url or the domain. I have checked the realm and I have that correct and I have used just empty strings providing only email and password. Could this be something to do with the fact that the site is using https? My code seems to work fine on my dev box without https but that may be a red herring.!

The only stack overflow questions that seem to cover my requirements have not got accepted answers and the docs are no help that I can see.

I now have such a large dent in my head from banging it against a brick wall that I am thinking of getting a square hat.

Please if anyone can give me the solution to this I will be forever in your debt! I might even e-Mail you an KitKat

like image 728
jamesc Avatar asked Jan 20 '12 00:01

jamesc


People also ask

How do you obtain a authentication token using WebView in android?

Basically you just add a WebAppInterface . The documentation describes it really well. Your android function should accept the token as a parameter and it should be called by your frontend after the user successfully logged in and has gotten his token.

How do you override a WebView?

If you want to override certain methods, you have to create a custom WebView class which extends WebView . Also, when you are inflating the WebView , make sure you are casting it to the correct type which is CustomWebView . CustomWebView webView = (CustomWebView) findViewById(R. id.

How do I open WebView in browser?

Android Webview open link in browser code snippet. myWebWiev = (WebView)findViewById(R. id. myWebWiev); myWebWiev.


2 Answers

This simple example abuses a page on HttpWatch since it's more fun with a working public example.

The resource in question, https://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?randomgarbage uses basic auth over HTTPS and can be loaded without authentication failure like this (tested using Android 2.3.7):

    WebView v = ...; // Your webview goes here. 
    try {
        HashMap<String, String> map = new HashMap<String, String>();
        // This test service takes the username "httpwatch" and a random
        // password. Repeating a password can lead to failure, so we create
        // a decently random one using UUID.
        String usernameRandomPassword = "httpwatch:" + UUID.randomUUID().toString();
        String authorization = "Basic " + Base64.encodeToString(usernameRandomPassword.getBytes("UTF-8"), Base64.NO_WRAP);
        map.put("Authorization", authorization);
        v.loadUrl("https://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?" + System.currentTimeMillis(), map);
    } catch (UnsupportedEncodingException e) {}

This works on ICS and Gingerbread. Don't have access to anything older than that, but loadUrl(String, Map<String,String>) was introduced in API level 8, so I don't see why it shouldn't work for that to.

Clarification for Nappy:

To support authentication for subsequent requests you supply a WebViewClient and do the following:

    webView.setWebViewClient(new WebViewClient(){
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url, <your map containing the Authorization header>);
            return true;
        }
    });
like image 155
Jens Avatar answered Oct 17 '22 14:10

Jens


It will work for https URL.In this if we are getting Untrusted_cer then we will ignore it

 webview.setWebViewClient(new WebViewClient(){
        @Override
        public void onReceivedHttpAuthRequest(WebView view,
                HttpAuthHandler handler, String host, String realm) {
            super.onReceivedHttpAuthRequest(view, handler, host, realm);
        }

        @Override
        public void onReceivedSslError(WebView view,
                SslErrorHandler handler, SslError error) {
            super.onReceivedSslError(view, handler, error);
            if(error.getPrimaryError()==SslError.SSL_UNTRUSTED){
                handler.proceed();
            }else{
                handler.proceed();
            }
        }

    });

I have no idea about second problem

like image 1
Tofeeq Ahmad Avatar answered Oct 17 '22 13:10

Tofeeq Ahmad