I\'ve created an application which loads a WebView. In order to login, the website requires basic authentication. When i try to access the website via the default browser, I
I know this is old, but adding another approach here as the ones above (using the onReceivedHttpAuthRequest) didn't work for me. Specifically some web pages don't prompt the user for Basic Authentication, they just redirect to the login screen. In my testing, Grafana happens to have this behavior by default.
So instead I added a HTTP Basic auth header using the below code:
HashMap headers = new HashMap<>();
String basicAuthHeader = android.util.Base64.encodeToString((username + ":" + password).getBytes(), android.util.Base64.NO_WRAP);
headers.put("Authorization", "Basic " + basicAuthHeader);
webView.loadUrl(url, headers);
This should bypass the auth prompt and just set the credentials automatically. Hope this helps someone looking for another solution.
Also, for anyone hoping to use the URL pattern of "https://username:password@url" - this is deprecated and I think most browsers will ignore it and throw away the credentials.
edit
I've come to the realization my above solution only works for the first request, and no subsequent requests after the page is loaded (i.e. for any further resources loaded).
In order for all subsequent requests to work, I had to override the following function for the web client:
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request){
if (username != null && password != null && username.length() > 0 && password.length() > 0) {
try {
OkHttpClient client = new OkHttpClient();
Request.Builder newRequestBuilder = new Request.Builder()
.url(request.getUrl().toString());
// add headers
Map currentHeaders = request.getRequestHeaders();
for (String header : currentHeaders.keySet()){
newRequestBuilder.addHeader(header, currentHeaders.get(header));
}
String basicAuthHeader = android.util.Base64.encodeToString((username + ":" + password).getBytes(), android.util.Base64.NO_WRAP);
newRequestBuilder.addHeader("Authorization", "Basic "+basicAuthHeader);
//make request
Request newRequest = newRequestBuilder.build();
Response response = client.newCall(newRequest).execute();
// respond with content
return new WebResourceResponse(response.header("content-type"), response.header("content-encoding", "utf-8"), response.body().byteStream());
} catch (Exception e) {
// if an exception occurs, just make a default request
return null;
}
} else {
// if no username and password, then make a default request
return null;
}
}
Unfortunately this code will not intercept POST requests, only GET requests, which limits what you can do with it.
Further, the above code should have some logic added to verify the domain of the initial request matches the domain of the intercepted requests before attaching the Authorization headers. Otherwise the Authorization header will be sent with all requests which could unintentionally send it to a different domain (e.g. loading resources from a CDN).