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