A basic implementation of basic access authentication using JASPIC
Basic access authentication is a crude mechanism to authenticate that's part of the HTTP standard. It allows both an agent to send username/password credentials and a server to request the agent to authenticate itself. This happens in a simple but standardized way.
The mechanism can be easily implemented using Java EE's JASPIC and a sprinkle of utility code from the experimental OmniSecurity project (which is currently being discussed as one of the possible options to simplify security in Java EE 8).
A basic implementation looks as follows:
public class BasicAuthModule extends HttpServerAuthModule {
@Override
public AuthStatus validateHttpRequest(HttpServletRequest request, HttpServletResponse response, HttpMsgContext httpMsgContext) throws AuthException {
String[] credentials = getCredentials(request);
if (!isEmpty(credentials)) {
UsernamePasswordIdentityStore identityStore = getReferenceOrNull(UsernamePasswordIdentityStore.class);
if (identityStore != null) {
if (identityStore.authenticate(credentials[0], credentials[1])) {
return httpMsgContext.notifyContainerAboutLogin(
identityStore.getUserName(),
identityStore.getApplicationRoles()
);
}
}
}
if (httpMsgContext.isProtected()) {
response.setHeader("WWW-Authenticate", "Basic realm=\"test realm:\"");
return httpMsgContext.responseUnAuthorized();
}
return httpMsgContext.doNothing();
}
private String[] getCredentials(HttpServletRequest request) {
String authorizationHeader = request.getHeader("Authorization");
if (!isEmpty(authorizationHeader) && authorizationHeader.startsWith("Basic ") ) {
return new String(parseBase64Binary(authorizationHeader.substring(6))).split(":");
}
return null;
}
}
Full code in the OmniSecurity repo
Using injection, the example can be simplified a little and will then look as follows:
public class BasicAuthModule extends HttpServerAuthModule {
@Inject
private UsernamePasswordIdentityStore identityStore;
@Override
public AuthStatus validateHttpRequest(HttpServletRequest request, HttpServletResponse response, HttpMsgContext httpMsgContext) throws AuthException {
String[] credentials = getCredentials(request);
if (!isEmpty(credentials) && identityStore.authenticate(credentials[0], credentials[1])) {
return httpMsgContext.notifyContainerAboutLogin(
identityStore.getUserName(),
identityStore.getApplicationRoles()
);
}
if (httpMsgContext.isProtected()) {
response.setHeader("WWW-Authenticate", "Basic realm=\"test realm:\"");
return httpMsgContext.responseUnAuthorized();
}
return httpMsgContext.doNothing();
}
private String[] getCredentials(HttpServletRequest request) {
String authorizationHeader = request.getHeader("Authorization");
if (!isEmpty(authorizationHeader) && authorizationHeader.startsWith("Basic ") ) {
return new String(parseBase64Binary(authorizationHeader.substring(6))).split(":");
}
return null;
}
}
Note that the JASPIC auth module as shown here is responsible for implementing the client/server interaction details. Validating the credentials (username/password here) and obtaining the username and roles is delegated to an identity store (which can e.g. be database or LDAP based).
Arjan Tijms
Comments
Post a Comment