Gandalf StormCrow
Gandalf StormCrow

Reputation: 26212

Web app and request authentication

I currently have a working web app, but I need to provide means for friend website to consume my data.

There is currently JSON response in place which retrieves some data from my website to caller. It's without authentication currently and I'd like to implement some kind of per request authentication.

My web app has users which are logged in and there is a authentication in place for that. But

I have 3 requests in total for which callers can get data off of my website, what would be the simplest way to add some kind of authentication just for those 3 requests?

I'm using play framework + java

Upvotes: 0

Views: 174

Answers (1)

leonardinius
leonardinius

Reputation: 142

Imo the best options for this would be in the order of simplicity:

  • Basic authentication (since it's possible to choose either to auth once and then do session-base user recognition or authorize on every request)
  • 2-way SSL
  • Combination of both

What toolkit do you use for authentication part?

I personally stuck with play-authenticate. So I might be able to answer you question in regard to this toolkit, please apply it to your particular toolkit as needed.

I will provide Basic authentication example as the easiest one. The benefit is: you could start with it and add on top it later (e.g. add Client certificate authentication via Apache later on).

So, my controller code snippet

@Restrict(value = @Group({"ROLE_WEB_SERVICE1"}), handler = BasicAuthHandler.class)
public static Result ws1() {
  return TODO;
}

And the authentification handler itself

public class BasicAuthHandler extends AbstractDeadboltHandler {
    public static final String HEADER_PREFIX = "Basic ";
    private static final String AUTHORIZATION = "authorization";
    private static final String WWW_AUTHENTICATE = "WWW-Authenticate";

    @Override
    public Result beforeAuthCheck(final Http.Context context) {
        return basicAuthenticate(context);
    }
    private Result basicAuthenticate(Http.Context context) {
        if (PlayAuthenticate.isLoggedIn(context.session())) {
            // user is logged in
            return null;
        }
        final String authHeader = context.request().getHeader(AUTHORIZATION);
        if (authHeader == null || !authHeader.toLowerCase().startsWith(HEADER_PREFIX.toLowerCase())) {
            return onAuthFailure(context, "Basic authentication header is missing");
        }
        final String auth = authHeader.substring(HEADER_PREFIX.length());
        final byte[] decodedAuth;
        final String[] credentials;
        try {
            decodedAuth = Base64.base64ToByteArray(auth);
            credentials = new String(decodedAuth, "UTF-8").split(":");
        } catch (final IOException e) {
            Logger.error("basicAuthenticate", e);
            return Results.internalServerError();
        }

        if (credentials.length != 2) {
            return onAuthFailure(context, "Could not authenticate with absent password");
        }

        final String username = credentials[0];
        final String password = credentials[1];

        final AuthUser authUser = new AuthUser(password, username);
        final Enum result = AuthProvider.getProvider().loginUser(authUser);

        if ("USER_LOGGED_IN".equals(result.name())) {
            PlayAuthenticate.storeUser(context.session(), authUser);
            return null;
        }
        return onAuthFailure(context, "Authenticate failure");
    }

    @Override
    public Subject getSubject(final Http.Context context) {
        // your implementation
    }

    @Override
    public Result onAuthFailure(final Http.Context context,
                                final String content) { 
        // your error hangling logic
        return super.onAuthFailure(context, content);
    }
}

Hopefully it fills in some blanks

Upvotes: 1

Related Questions