Skip to main content

How does the browser's native login prompt work and how to use it programmatically

This is another one of those rather interesting problems that I had to solve at my day job and since I knew little about how to solve it when I first came across it, I am going to blog about it. I am sure there are others like me, who may not know how to solve it when tasked with such a problem.

Problem

So I am working on a Java based project at work(lets call it Project X)  for which my latest task was to change the way it handles login.

Problem details

I think it's best I provide some context before I describe my problem, so here we go,

You see when you try to access a certain restricted area of a web-app when not logged-in the browser will show you a login prompt, and only when you enter the right credentials, will you be able to access that area of a web-app. That entire process of seeing the login prompt, entering the credentials etc requires human intervention and my task was to achieve all that programmatically i.e. without any human intervention for Project X.

Great!! the problem is now clear, so let's look at the problem in the context of Project X in a bit more detail. In Project X, we have a login-page that  calls a certain Servlet and passes the username and password, now my task was to invoke that RESTful endpoint while passing the username and password and the RESTful endpoint will respond with a cookie (assuming the credentials are correct) that has a session token that can be stored and used for subsequent requests.

How does the browser's native login prompt work?

This blog post by Steven Sanderson explains how it all works and it does so rather well. In the interest of completeness of this post, I will summarise it here
  1. When you try to access a certain restricted resource by typing the url in the browser
  2. The browser gets a HTTP 401 unauthorized response
  3. After which the browser shows you a login prompt
  4. Then you enter the username and password and click log-in
  5. The browser re-submits the request but this time with an extra header                                           i.e. Authorization: Basic username password
  6. The username and password are base64 encoded so the header would actually look something like this                                                                                                                   Authorization:Basic ILQtaW46YWRtaW4=
  7. If you were successfully authenticated, you will access the resource you were trying to access

So what was my goal?

Add functionality similar to how the browser's native login handling to the backend java code for Project X, get the response and extract and store a cookie sent as a part of the response. 

Solution

Turns out, once I fully understood the problem, it was actually quite easy to accomplish that with the Apache HttpClient library. In fact, the when you download and unzip the libs from here, in the contents of the httpcomponents-client-4.4.1(at the time of writing) folder, you will find some sample code in the examples folder within it. Once again in the interest of completeness of this post, I will add some sample code in this post.

public class ClientAuthentication {
    public static void main(String[] args) throws Exception {
        String host = "";
        int port = 0000;
        String username = "username";
        String password = "password";
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(
            new AuthScope(host, port),
            new UsernamePasswordCredentials(username, password));
    final BasicCookieStore cookieStore = new BasicCookieStore();
    CloseableHttpClient httpclient = HttpClients.custom()
            .setDefaultCredentialsProvider(credsProvider)
            .setDefaultCookieStore(cookieStore)
            .build();
    try {
        String urlToQuery =""; 
        HttpGet httpget = new HttpGet(urlToQuery);
        ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
            @Override
            public String handleResponse(
                    final HttpResponse response) throws ClientProtocolException, IOException {
                List<Cookie> cookies = cookieStore.getCookies();
                if (cookies.isEmpty()) {
                    System.out.println("None");
                } else {
                    for (int i = 0; i < cookies.size(); i++) {
                        System.out.println("- " + cookies.get(i).toString());
                    }
                }
                return "";
            }

        };
        httpclient.execute(httpget, responseHandler);
    } finally {
        httpclient.close();
    }
    }
}
Now the above example works great with the 4.4.1  version of the libs, but you see Project X uses 4.1.2 version of the libs and since this was something very basic, I had to figure out how to make it work with the older libs. What you see below is code that does something similar but with the older version of the libs.

public class AuthWithFourPointOne {

    public static void main(String[] args) throws Exception {
        String host = "";
        int port = 0000;
        String username = "username";
        String password = "password";
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(new AuthScope(host, port), new UsernamePasswordCredentials(username, password));
        DefaultHttpClient httpclient = new DefaultHttpClient();
        httpclient.setCredentialsProvider(credsProvider);
        try {
            String url = "";
            HttpGet httpGet = new HttpGet(url);
            HttpResponse response = httpclient.execute(httpGet);
            String cookie = "";
            //in my case the cookie in the header was called Set-Cookie
            for(Header header:response.getAllHeaders()){
                if(header.getName().contains("Set-Cookie")) {
                    cookie = header.getValue();
                }
            }
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
    }
}

Comments

Popular posts from this blog

Html5 based widget for an iOS app: Today extension powered by the Ionic framework

At some point the thought of adding a Widget to my iOS app came to mind which was followed by starting work on adding a widget for my app, My Day Todos . Obviously the first step was to learn how to add a Widget to an iOS app and in that learning process I discovered many things about widgets in iOS first of which was a widget in iOS is a an app extension i.e a  Today Extension . While I am still haven't finished working on the widget for my iOS app, I thought I would take some time out and share what I have learned. In this post, I will share a few important tips and provide an example of how to add a Widget to an iOS app and have the widget UI powered by Html5 via  Ionic framework . I added some code to my Github repo, Html5StarterAppWithSwift in order to show how this can be achieved. There are already too many tutorials out on the Web on how to add a Today extension to an iOS app so I won't be including that here. Instead I will focus on sharing some of the useful tip...

Build a Full-Stack Image Upload App with Node.js, Express, React, and Vite (Beginner Tutorial)

 If you’re new to full-stack web development and want a hands-on project to practice React frontend integration with a Node.js + Express backend , this tutorial is for you. In this guide, we’ll walk through a simple but powerful app that lets users upload images, store them on the server, and display them back in the browser. This project is based on my GitHub repo: node-express-react-simple-fileupload . It’s designed to be beginner-friendly, SEO-optimized, and a great starting point for anyone learning JavaScript full-stack development . 🛠️ Technologies Used Here’s the tech stack powering this project: Node.js – JavaScript runtime for the backend. Express.js – Lightweight web framework for building REST APIs. Multer – Middleware for handling file uploads. CORS – Enables cross-origin requests between frontend and backend. React.js – Frontend library for building user interfaces. Vite – Fast development server and build tool for React. Fetch API – For making HTTP requests ...

App update, discovering Protractor(testing) and an Angularjs State machine

So for the last couple of weeks, I have not be able to update my blog or finish a couple of the posts that I started writing. Well, I have...been a bit busy, with some the following things,  Testing my app I have been using the app( iOS ) on my iPhone for the past couple of months now, which is both good and bad. The good thing is I can test it and the bad thing is, I can use it every day. Part of the reason, I started building this app is to have something that I can and like to use everyday and since I am already using it, the incentive to release it is not as high as if it were something that I could not use. Anyway I did make some good progress over the last couple of weeks, like  Delete the app from my iPhone and do a clean install: this did help me find a few simple bugs that would pop-up when the app is first installed GET AN APP ICON, FINALLY! this was a bit of a hurdle and I thanks to Fiverr  and fivercrazyguy , I finally have my app icon. The day job ...