Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTP Basic Authentication for Play framework 2.4

I am looking some way to make some authentication for my play framework app: I want allow/disallow the whole access to non authenticated users

Is there exists some working module/solution for it? I don't need any forms for auth, just 401 HTTP response for non authenticated users (like Apache .htacccess "AuthType Basic" mode).

like image 659
Oleg Avatar asked Feb 04 '26 12:02

Oleg


2 Answers

I've updated Jonck van der Kogel's answer to be more strict in parsing the authorization header, to not fail with ugly exceptions if the auth header is invalid, to allow passwords with ':', and to work with Play 2.6:

So, BasicAuthAction class:

import java.io.UnsupportedEncodingException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

import org.apache.commons.codec.binary.Base64;

import play.Logger;
import play.Logger.ALogger;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Http.Context;
import play.mvc.Result;

public class BasicAuthAction extends Action<Result> {
    private static ALogger log = Logger.of(BasicAuthAction.class);

    private static final String AUTHORIZATION = "Authorization";
    private static final String WWW_AUTHENTICATE = "WWW-Authenticate";
    private static final String REALM = "Basic realm=\"Realm\"";

    @Override
    public CompletionStage<Result> call(Context context) {
        String authHeader = context.request().getHeader(AUTHORIZATION);
        if (authHeader == null) {
            context.response().setHeader(WWW_AUTHENTICATE, REALM);
            return CompletableFuture.completedFuture(status(Http.Status.UNAUTHORIZED, "Needs authorization"));
        }

        String[] credentials;
        try {
            credentials = parseAuthHeader(authHeader);
        } catch (Exception e) {
            log.warn("Cannot parse basic auth info", e);
            return CompletableFuture.completedFuture(status(Http.Status.FORBIDDEN, "Invalid auth header"));
        }

        String username = credentials[0];
        String password = credentials[1];
        boolean loginCorrect = checkLogin(username, password);

        if (!loginCorrect) {
            log.warn("Incorrect basic auth login, username=" + username);
            return CompletableFuture.completedFuture(status(Http.Status.FORBIDDEN, "Forbidden"));
        } else {
            context.request().setUsername(username);
            log.info("Successful basic auth login, username=" + username);
            return delegate.call(context);
        }
    }

    private String[] parseAuthHeader(String authHeader) throws UnsupportedEncodingException {
        if (!authHeader.startsWith("Basic ")) {
            throw new IllegalArgumentException("Invalid Authorization header");
        }

        String[] credString;
        String auth = authHeader.substring(6);
        byte[] decodedAuth = new Base64().decode(auth);
        credString = new String(decodedAuth, "UTF-8").split(":", 2);
        if (credString.length != 2) {
            throw new IllegalArgumentException("Invalid Authorization header");
        }

        return credString;
    }

    private boolean checkLogin(String username, String password) {
        /// change this
        return username.equals("vlad");
    }
}

And then, in controller classes:

@With(BasicAuthAction.class)
public Result authPage() {
    String username = request().username();
    return Result.ok("Successful login as user: " + username + "! Here's your data: ...");
}
like image 79
Vlad Dinulescu Avatar answered Feb 07 '26 00:02

Vlad Dinulescu


You can try this filter:

https://github.com/Kaliber/play-basic-authentication-filter

It looks pretty simple to use and configure.

like image 42
marcospereira Avatar answered Feb 07 '26 01:02

marcospereira



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!