CMSgov/dpc-app

View on GitHub
dpc-api/src/main/java/gov/cms/dpc/api/auth/DPCAuthDynamicFeature.java

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
package gov.cms.dpc.api.auth;

import gov.cms.dpc.api.auth.annotations.AdminOperation;
import gov.cms.dpc.api.auth.annotations.Authorizer;
import gov.cms.dpc.api.auth.annotations.PathAuthorizer;
import gov.cms.dpc.api.auth.annotations.Public;
import io.dropwizard.auth.AuthDynamicFeature;
import org.glassfish.jersey.server.model.AnnotatedMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;
import java.lang.annotation.Annotation;

/**
 * Wrapper class which injects the DPC specific authenticators into the {@link AuthDynamicFeature} provider.
 * This way we can avoid authn/authz on public endpoints and dynamically determine when to apply security.
 */
@Provider
public class DPCAuthDynamicFeature implements DynamicFeature {

    private static final Logger logger = LoggerFactory.getLogger(DPCAuthDynamicFeature.class);

    private final AuthFactory factory;

    @Inject
    public DPCAuthDynamicFeature(AuthFactory factory) {
        this.factory = factory;
    }

    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context) {


        final AnnotatedMethod am = new AnnotatedMethod(resourceInfo.getResourceMethod());

        // Check for Admin annotated params
        if (isMethodClassAnnotated(AdminOperation.class, resourceInfo, am)) {
            logger.trace("Registering Admin authorizer on method {}", am);
            context.register(this.factory.createAdminAuthorizer());
            return;
        }

        // Check for @PathAuthorizer annotated param
        if (isMethodClassAnnotated(PathAuthorizer.class, resourceInfo, am)) {
            logger.trace("Registering PathAuthorizer param on method {}", am.toString());
            final PathAuthorizer pa = am.getAnnotation(PathAuthorizer.class);
            context.register(this.factory.createPathAuthorizer(pa));
            return;
        }

        // Check for @Authorized annotated param
        if (isMethodClassAnnotated(Authorizer.class, resourceInfo, am)) {
            logger.trace("Registering Auth param on method {}", am.toString());
            context.register(this.factory.createStandardAuthorizer());
            return;
        }

        // If we're public don't do anything
        if (isMethodClassAnnotated(Public.class, resourceInfo, am)) {
            return;
        }
    }

    private boolean isMethodClassAnnotated(Class<? extends Annotation> annotation, ResourceInfo resourceInfo, AnnotatedMethod am) {
        return am.isAnnotationPresent(annotation)
                || (resourceInfo.getResourceClass().getAnnotation(annotation) != null);
    }
}