All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.robe.auth.token.jersey.TokenFactory Maven / Gradle / Ivy

package io.robe.auth.token.jersey;

import com.google.common.base.Optional;
import com.google.common.hash.Hashing;
import io.dropwizard.auth.AuthenticationException;
import io.dropwizard.auth.Authenticator;
import io.robe.auth.Credentials;
import io.robe.auth.token.Token;
import io.robe.auth.token.TokenManager;
import org.glassfish.jersey.server.internal.inject.AbstractContainerRequestValueFactory;
import org.glassfish.jersey.uri.UriTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.Response;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class TokenFactory extends AbstractContainerRequestValueFactory {
    private static final Logger LOGGER = LoggerFactory.getLogger(TokenFactory.class);

    public static Authenticator authenticator;

    public static String tokenKey;

    private boolean required = true;

    public TokenFactory(boolean required) {
        this.required = required;
    }

    public TokenFactory() {
    }

    public static Credentials createEmptyCredentials() {

        return new Credentials() {
            @Override
            public String getUserId() {
                return null;
            }

            @Override
            public String getUsername() {
                return null;
            }

            @Override
            public String getName() {
                return null;
            }
        };
    }

    public boolean isRequired() {
        return required;
    }

    public void setRequired(boolean required) {
        this.required = required;
    }

    @Override
    public Credentials provide() {
        Cookie tokenCookie = getContainerRequest().getCookies().get(tokenKey);

        if (isRequired()) {


            if (tokenCookie == null) {
                throw new WebApplicationException(Response.Status.UNAUTHORIZED);
            } else if (nullOrEmpty(tokenCookie.getValue())) {
                throw new WebApplicationException(Response.Status.UNAUTHORIZED);
            } else {
                try {
                    if (!isRealOwnerOfToken(tokenCookie)) {
                        throw new WebApplicationException(Response.Status.UNAUTHORIZED);
                    }
                    Optional result = authenticator.authenticate(tokenCookie.getValue());

                    if (!result.isPresent()) {
                        throw new WebApplicationException(Response.Status.UNAUTHORIZED);
                    } else if (!isAuthorized(result.get(), getContainerRequest().getUriInfo().getMatchedTemplates(), getContainerRequest().getMethod())) {
                        throw new WebApplicationException(Response.Status.FORBIDDEN);
                    } else {
                        return result.get();
                    }
                } catch (io.dropwizard.auth.AuthenticationException e) {
                    LOGGER.error("Authentication Exception  by Dropwizard", e);
                    throw new WebApplicationException(Response.Status.PRECONDITION_FAILED);
                } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
                    LOGGER.error("Authentication Exception  (Is Real ownwer of token) ", e);
                    throw new WebApplicationException(Response.Status.PRECONDITION_FAILED);
                }
            }
        } else {
            if (tokenCookie == null) {
                return createEmptyCredentials();
            } else {
                try {
                    Optional result = authenticator.authenticate(tokenCookie.getValue());
                    if (result.isPresent()) {
                        return result.get();
                    } else {
                        return createEmptyCredentials();
                    }
                } catch (AuthenticationException e) {
                    // TODO ignore this error
                    return createEmptyCredentials();
                }

            }
        }
    }

    private boolean isRealOwnerOfToken(Cookie tokenCookie) throws IllegalAccessException, InvocationTargetException, InstantiationException {
        LOGGER.debug("HttpContext : " + this.getContainerRequest().getPath(true) + " Cookie : " + tokenCookie);
        Token token = TokenManager.getInstance().createToken(tokenCookie.getValue());
        String hash = generateAttributesHash();
        return hash.equals(token.getAttributesHash());

    }

    private boolean nullOrEmpty(String token) {
        return token == null || token.length() == 0;
    }


    /**
     * Merges all path patterns and and creates a single string value which will be equal with service methods path
     * annotation value and HTTP method type. Generated string will be used for permission checks.
     *
     * @param token            for checking permission list
     * @param matchedTemplates matched templates of context. They will be merged with reverse order
     * @param method           HTTP Method of the request. Will be merged with
     * @return true if user is Authorized.
     */
    private boolean isAuthorized(Token token, List matchedTemplates, String method) {
        StringBuilder path = new StringBuilder();
        // Merge all path templates and generate a path.
        for (UriTemplate template : matchedTemplates) {
            path.insert(0, template.getTemplate());
        }
        path.append(":").append(method);

        //Look at user permissions to see if the service is permitted.
        return token.getPermissions().contains(path.toString());
    }


    public String generateAttributesHash() {
        StringBuilder attr = new StringBuilder();
        attr.append(this.getContainerRequest().getHeaderString("User-Agent"));
        return Hashing.sha256().hashString(attr.toString(), StandardCharsets.UTF_8).toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy