@RequiredRole with BaseCertLoginModule

3

My system authenticates the client (it's a web service) through BaseCertLoginModule , a JBoss class based on the JaaS specification. In fact my project extends this class, and this extension is called upon every request to decide whether the user has access to the web service or not. I do this by getting the two-way SSL (SSL two-way) serial and searching the database with this serial.

This all (authentication) is working legal. What I wanted now is resolve the authorization. I wanted to use the @RequiredRole annotation because I already set user roles in my LoginModule . I thought I would just do this:

@Override
@WebMethod
@RequiredRole("MASTER")
public void cancelarLaudo(CancelamentoLaudoRequest cancelamentoLaudoRequest)...

Where cancelarLaudo is an operation of my SOAP web service.

But it did not work. :)

What else would I have to do? I've read Demoiselle documentation, but it was not clear how I would work with the LoginModule scheme I already have.

My LoginModule :

package br.gov.serpro.sislvws.security.loginmodule;

import java.security.Principal;
import java.security.acl.Group;
import java.security.cert.X509Certificate;

import javax.persistence.NoResultException;
import javax.security.auth.login.LoginException;

import org.jboss.logging.Logger;
import org.jboss.security.SimpleGroup;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.auth.spi.BaseCertLoginModule;

import br.gov.frameworkdemoiselle.util.Beans;
import br.gov.serpro.sislv.entity.CertificadoDigital;
import br.gov.serpro.sislv.entity.Entidade;
import br.gov.serpro.sislv.persistence.EntidadeDAO;

public class SislvLoginModule extends BaseCertLoginModule {

    private Logger logger = Logger.getLogger(this.getClass());

    private EntidadeDAO entidadeDAO;

    public SislvLoginModule() {
        entidadeDAO = Beans.getReference(EntidadeDAO.class);
    }

    @Override
    protected Principal createIdentity(String arg0) throws Exception {
        X509Certificate certificate = (X509Certificate) getCredentials();
        try {
            Principal principal = new SislvPrincipal(certificate);
            log.info("Usuário identificado: " + principal);
            return principal;
        } catch (Exception e) {
            String message = "Falha ao tentar autenticar o certificado " + certificate.toString();
            logger.error(message, e);
            throw e;
        }
    }

    @Override
    protected Group[] getRoleSets() throws LoginException {

        CertificadoDigital certificado = certificado();

        try {
            Entidade entidade = entidadeDAO.findBy(certificado);
            String role = entidade.getTipoEntidade().toString();
            SimpleGroup roles = new SimpleGroup("Roles");
            SimplePrincipal user = new SimplePrincipal(role);
            roles.addMember(user);
            return new Group[] { roles };
        } catch (NoResultException e) {
            String msg = certificado + " não autorizado a acessar o web service.";
            logger.error(msg);
            throw new LoginException(msg);
        } catch (Exception e) {
            logger.error("Erro inesperado durante a autenticação", e);
            throw new LoginException();
        }
    }

    private CertificadoDigital certificado() throws LoginException {
        SislvPrincipal identity = null;
        try {
            identity = (SislvPrincipal) getIdentity();
            CertificadoDigital cert = new CertificadoDigital();
            cert.setCommonName(identity.getCommonName());
            cert.setSerial(identity.getSerial());
            cert.setCommonNameEmissor(identity.getCommonNameEmissor());
            return cert;
        } catch (Exception e) {
            logger.error("Erro inesperado durante a autenticação", e);
            throw new LoginException();
        }
    }

}

Configuring JBoss to enable LoginModule :

            <security-domain name="SislvSecurityDomain">
                <authentication>
                    <login-module code="br.gov.serpro.sislvws.security.loginmodule.SislvLoginModule" flag="required">
                        <module-option name="verifier" value="org.jboss.security.auth.certs.AnyCertVerifier" />
                    </login-module>
                </authentication>
                ...
    
asked by anonymous 07.07.2015 / 16:28

1 answer

1

Oops, the main thing missing was activating the RequiredRoleInterceptor interceptor in beans.xml . Also, I've extended the ServletAuthorizer class of Demoiselle to implement the hasRole method. And, finally, this class has been registered in demoiselle.properties.

Now the solution is working, but I still wanted to improve one aspect.

Here's my empowering class:

    package br.gov.serpro.sislvws.ws.autorizacao;

    import javax.enterprise.context.RequestScoped;
    import javax.inject.Inject;

    import br.gov.frameworkdemoiselle.security.ServletAuthorizer;
    import br.gov.serpro.sislvws.security.loginmodule.RequestAutenticado;

    @RequestScoped
    public class RoleBasedAuthorizer extends ServletAuthorizer {

        private static final long serialVersionUID = 1L;

        @Inject
        private RequestAutenticado requestAutenticado;

        @Override
        public boolean hasRole(String role) throws Exception {
            String tipoEntidade = requestAutenticado.getEntidadeCliente().getTipoEntidade().toString();
            return tipoEntidade.equals(role);
        }

    }

In this solution, there is a repetition of the logic to define the role of the logged in user. This logic appears getRoleSets of login module and hasRole of authorizer. What I think would be best if the role definition was just the login module, and if in the authorizer I was able to retrieve which role has already been defined there in the login module.

I have tried searches like "(jboss | jaas) retrieve role define on login module", but I still can not solve.

    
30.07.2015 / 14:51