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

com.hp.autonomy.hod.client.api.authentication.AuthenticationServiceImpl Maven / Gradle / Ivy

There is a newer version: 0.25.3
Show newest version
/*
 * Copyright 2015-2016 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

package com.hp.autonomy.hod.client.api.authentication;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hp.autonomy.hod.client.api.authentication.tokeninformation.ApplicationTokenInformation;
import com.hp.autonomy.hod.client.api.authentication.tokeninformation.CombinedTokenInformation;
import com.hp.autonomy.hod.client.api.authentication.tokeninformation.DeveloperTokenInformation;
import com.hp.autonomy.hod.client.api.authentication.tokeninformation.UnboundTokenInformation;
import com.hp.autonomy.hod.client.api.authentication.tokeninformation.UserTokenInformation;
import com.hp.autonomy.hod.client.config.HodServiceConfig;
import com.hp.autonomy.hod.client.error.HodErrorException;
import com.hp.autonomy.hod.client.token.TokenProxy;
import com.hp.autonomy.hod.client.token.TokenRepository;
import com.hp.autonomy.hod.client.token.TokenRepositoryException;
import com.hp.autonomy.hod.client.util.Hmac;
import com.hp.autonomy.hod.client.util.Request;
import retrofit.client.Response;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Default implementation of {@link AuthenticationService}
 */
public class AuthenticationServiceImpl implements AuthenticationService {
    private static final String REDIRECT_URL = "redirect_url";

    // Fake origin to use when making authenticate combined requests to HOD
    // TODO: This should be removed once "origin" becomes optional (HOD-4031)
    private static final String ORIGIN = "http://www.example.com";

    private static final Request TOKEN_INFORMATION_REQUEST = new Request<>(Request.Verb.GET, AuthenticationBackend.GET_TOKEN_INFORMATION_PATH, null, null);

    private static final TypeReference> TOKEN_TYPE_REFERENCE = new TypeReference>() {};
    private static final TypeReference> DEVELOPER_INFORMATION_TYPE = new TypeReference>() {};
    private static final TypeReference> COMBINED_INFORMATION_TYPE = new TypeReference>() {};
    private static final TypeReference> USER_INFORMATION_TYPE = new TypeReference>() {};
    private static final TypeReference> UNBOUND_INFORMATION_TYPE = new TypeReference>() {};
    private static final TypeReference> APPLICATION_INFORMATION_TYPE = new TypeReference>() {};
    private static final TypeReference> AUTHENTICATE_COMBINED_GET_TYPE = new TypeReference>() {};

    private final AuthenticationBackend authenticationBackend;
    private final TokenRepository tokenRepository;
    private final ObjectMapper objectMapper;
    private final String endpoint;

    private final Hmac hmac = new Hmac();

    /**
     * Creates a new AuthenticationServiceImpl with the given configuration
     * @param hodServiceConfig The configuration to use
     */
    public AuthenticationServiceImpl(final HodServiceConfig hodServiceConfig) {
        authenticationBackend = hodServiceConfig.getRestAdapter().create(AuthenticationBackend.class);
        tokenRepository = hodServiceConfig.getTokenRepository();
        endpoint = hodServiceConfig.getEndpoint();
        objectMapper = hodServiceConfig.getObjectMapper();
    }

    @Override
    public  TokenProxy authenticateApplication(
            final ApiKey apiKey,
            final String applicationName,
            final String domain,
            final T tokenType
    ) throws HodErrorException {
        final Response response = authenticationBackend.authenticateApplication(apiKey, applicationName, domain, tokenType.getParameter());
        final AuthenticationToken token = parseToken(response, EntityType.Application.INSTANCE, tokenType);
        return insertToken(token);
    }

    @Override
    public AuthenticationToken authenticateDeveloper(final ApiKey apiKey, final UUID tenantUuid, final String email) throws HodErrorException {
        final Response response = authenticationBackend.authenticateDeveloper(apiKey, tenantUuid.toString(), email);
        return parseToken(response, EntityType.Developer.INSTANCE, TokenType.HmacSha1.INSTANCE);
    }

    @Override
    public  AuthenticationToken authenticateUnbound(final ApiKey apiKey, final T tokenType) throws HodErrorException {
        final Response response = authenticationBackend.authenticateUnbound(apiKey, tokenType.getParameter());
        return parseToken(response, EntityType.Unbound.INSTANCE, tokenType);
    }

    @Override
    public List authenticateCombinedGet(
            final AuthenticationToken combinedSsoToken,
            final AuthenticationToken appToken
    ) throws HodErrorException {
        final String nonce = generateNonce();

        final Map> queryParameters = new HashMap<>();
        queryParameters.put(AuthenticationBackend.NONCE_PARAMETER, Collections.singletonList(nonce));
        queryParameters.put(AuthenticationBackend.ALLOWED_ORIGINS_PARAMETER, Collections.singletonList(ORIGIN));

        final Request request = new Request<>(
                Request.Verb.GET,
                AuthenticationBackend.COMBINED_PATH,
                queryParameters,
                null
        );

        final Response response = authenticationBackend.authenticateCombinedGet(combinedSsoToken, hmac.generateToken(request, appToken), ORIGIN, ORIGIN, nonce);

        try {
            return objectMapper.readValue(response.getBody().in(), AUTHENTICATE_COMBINED_GET_TYPE);
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public  AuthenticationToken authenticateCombined(
            final AuthenticationToken combinedSsoToken,
            final AuthenticationToken appToken,
            final String applicationDomain,
            final String applicationName,
            final T tokenType
    ) throws HodErrorException {
        final Map> queryParameters = Collections.singletonMap(AuthenticationBackend.ALLOWED_ORIGINS_PARAMETER, Collections.singletonList(ORIGIN));

        final Map> body = createBaseCombinedBody(applicationName, applicationDomain, tokenType);
        body.put(AuthenticationBackend.NONCE_PARAMETER, Collections.singletonList(generateNonce()));

        final Request request = new Request<>(Request.Verb.POST, AuthenticationBackend.COMBINED_PATH, queryParameters, body);
        final String signature = hmac.generateToken(request, appToken);

        final Response response = authenticationBackend.authenticateCombined(
                combinedSsoToken,
                signature,
                ORIGIN,
                ORIGIN,
                generateNonce(),
                applicationDomain,
                applicationName,
                null,
                null,
                tokenType.getParameter()
        );

        return parseToken(response, EntityType.Combined.INSTANCE, tokenType);
    }

    @Override
    public  AuthenticationToken authenticateCombined(
            final AuthenticationToken combinedSsoToken,
            final AuthenticationToken appToken,
            final String applicationDomain,
            final String applicationName,
            final String userstoreDomain,
            final String userstoreName,
            final T tokenType
    ) throws HodErrorException {
        final Map> queryParameters = Collections.singletonMap(AuthenticationBackend.ALLOWED_ORIGINS_PARAMETER, Collections.singletonList(ORIGIN));

        final Map> body = createUserStoreCombinedBody(applicationName, applicationDomain, tokenType, userstoreDomain, userstoreName);
        body.put(AuthenticationBackend.NONCE_PARAMETER, Collections.singletonList(generateNonce()));

        final Request request = new Request<>(Request.Verb.POST, AuthenticationBackend.COMBINED_PATH, queryParameters, body);
        final String signature = hmac.generateToken(request, appToken);

        final Response response = authenticationBackend.authenticateCombined(
                combinedSsoToken,
                signature,
                ORIGIN,
                ORIGIN,
                generateNonce(),
                applicationDomain,
                applicationName,
                userstoreDomain,
                userstoreName,
                tokenType.getParameter()
        );

        return parseToken(response, EntityType.Combined.INSTANCE, tokenType);
    }

    @Override
    public CombinedTokenInformation getCombinedTokenInformation(final AuthenticationToken token) throws HodErrorException {
        final Response response = authenticationBackend.getTokenInformation(token.toString());
        return parseTokenInformation(response, COMBINED_INFORMATION_TYPE);
    }

    @Override
    public CombinedTokenInformation getHmacCombinedTokenInformation(final AuthenticationToken token) throws HodErrorException {
        final Response response = authenticationBackend.getTokenInformation(hmac.generateToken(TOKEN_INFORMATION_REQUEST, token));
        return parseTokenInformation(response, COMBINED_INFORMATION_TYPE);
    }

    @Override
    public DeveloperTokenInformation getDeveloperTokenInformation(final AuthenticationToken token) throws HodErrorException {
        final Response response = authenticationBackend.getTokenInformation(hmac.generateToken(TOKEN_INFORMATION_REQUEST, token));
        return parseTokenInformation(response, DEVELOPER_INFORMATION_TYPE);
    }

    @Override
    public ApplicationTokenInformation getApplicationTokenInformation(final TokenProxy tokenProxy) throws HodErrorException {
        final AuthenticationToken token = getToken(tokenProxy);

        final Response response = authenticationBackend.getTokenInformation(token.toString());
        return parseTokenInformation(response, APPLICATION_INFORMATION_TYPE);
    }

    @Override
    public ApplicationTokenInformation getHmacApplicationTokenInformation(final TokenProxy tokenProxy) throws HodErrorException {
        final AuthenticationToken token = getToken(tokenProxy);

        final Response response = authenticationBackend.getTokenInformation(hmac.generateToken(TOKEN_INFORMATION_REQUEST, token));
        return parseTokenInformation(response, APPLICATION_INFORMATION_TYPE);
    }

    @Override
    public UserTokenInformation getUserTokenInformation(final TokenProxy tokenProxy) throws HodErrorException {
        final AuthenticationToken token = getToken(tokenProxy);

        final Response response = authenticationBackend.getTokenInformation(token.toString());
        return parseTokenInformation(response, USER_INFORMATION_TYPE);
    }

    @Override
    public UserTokenInformation getHmacUserTokenInformation(final TokenProxy tokenProxy) throws HodErrorException {
        final AuthenticationToken token = getToken(tokenProxy);

        final Response response = authenticationBackend.getTokenInformation(hmac.generateToken(TOKEN_INFORMATION_REQUEST, token));
        return parseTokenInformation(response, USER_INFORMATION_TYPE);
    }

    @Override
    public UnboundTokenInformation getUnboundTokenInformation(final AuthenticationToken token) throws HodErrorException {
        final Response response = authenticationBackend.getTokenInformation(token.toString());
        return parseTokenInformation(response, UNBOUND_INFORMATION_TYPE);
    }

    @Override
    public UnboundTokenInformation getHmacUnboundTokenInformation(final AuthenticationToken token) throws HodErrorException {
        final Response response = authenticationBackend.getTokenInformation(hmac.generateToken(TOKEN_INFORMATION_REQUEST, token));
        return parseTokenInformation(response, UNBOUND_INFORMATION_TYPE);
    }

    @Override
    public SignedRequest combinedGetRequest(final Collection allowedOrigins, final AuthenticationToken token) {
        final Map> queryParameters = new HashMap<>();
        queryParameters.put(AuthenticationBackend.ALLOWED_ORIGINS_PARAMETER, new ArrayList<>(allowedOrigins));

        final Request request = new Request<>(Request.Verb.GET, AuthenticationBackend.COMBINED_PATH, queryParameters, null);
        return SignedRequest.sign(hmac, endpoint, token, request);
    }

    @Override
    public SignedRequest combinedPatchRequest(final Collection allowedOrigins, final AuthenticationToken token) {
        final Map> queryParameters = new HashMap<>();
        queryParameters.put(AuthenticationBackend.ALLOWED_ORIGINS_PARAMETER, new ArrayList<>(allowedOrigins));

        final Request request = new Request<>(Request.Verb.PATCH, AuthenticationBackend.COMBINED_PATH, queryParameters, null);
        return SignedRequest.sign(hmac, endpoint, token, request);
    }

    @Override
    public SignedRequest combinedPatchRequest(final Collection allowedOrigins, final String redirectUrl, final AuthenticationToken token) {
        final Map> queryParameters = new HashMap<>();
        queryParameters.put(AuthenticationBackend.ALLOWED_ORIGINS_PARAMETER, new ArrayList<>(allowedOrigins));
        queryParameters.put(REDIRECT_URL, Collections.singletonList(redirectUrl));

        final Request request = new Request<>(Request.Verb.PATCH, AuthenticationBackend.COMBINED_PATH, queryParameters, null);
        return SignedRequest.sign(hmac, endpoint, token, request);
    }

    @Override
    public SignedRequest combinedRequest(
            final Collection allowedOrigins,
            final AuthenticationToken token,
            final String applicationDomain,
            final String applicationName,
            final TokenType tokenType
    ) {
        final Map> body = createBaseCombinedBody(applicationName, applicationDomain, tokenType);
        return createCombinedRequest(token, allowedOrigins, body);
    }

    @Override
    public SignedRequest combinedRequest(
            final Collection allowedOrigins,
            final AuthenticationToken token,
            final String applicationDomain,
            final String applicationName,
            final String userStoreDomain,
            final String userStoreName,
            final TokenType tokenType
    ) {
        final Map> body = createUserStoreCombinedBody(applicationName, applicationDomain, tokenType, userStoreDomain, userStoreName);
        return createCombinedRequest(token, allowedOrigins, body);
    }

    @Override
    public SignedRequest combinedRequest(
            final Collection allowedOrigins,
            final AuthenticationToken token,
            final String applicationDomain,
            final String applicationName,
            final String userStoreDomain,
            final String userStoreName,
            final TokenType tokenType,
            final boolean useNonce
    ) {
        final Map> body = createUserStoreCombinedBody(applicationName, applicationDomain, tokenType, userStoreDomain, userStoreName);

        if (useNonce) {
            body.put(AuthenticationBackend.NONCE_PARAMETER, Collections.singletonList(generateNonce()));
        }

        return createCombinedRequest(token, allowedOrigins, body);
    }

    private String generateNonce() {
        return UUID.randomUUID().toString();
    }

    private SignedRequest createCombinedRequest(
            final AuthenticationToken token,
            final Collection allowedOrigins,
            final Map> body
    ) {
        final Map> queryParameters = new HashMap<>();
        queryParameters.put(AuthenticationBackend.ALLOWED_ORIGINS_PARAMETER, new ArrayList<>(allowedOrigins));

        final Request request = new Request<>(Request.Verb.POST, AuthenticationBackend.COMBINED_PATH, queryParameters, body);
        return SignedRequest.sign(hmac, endpoint, token, request);
    }

    private Map> createBaseCombinedBody(
            final String applicationName,
            final String applicationDomain,
            final TokenType tokenType
    ) {
        final Map> body = new HashMap<>();
        body.put(AuthenticationBackend.DOMAIN_PARAMETER, Collections.singletonList(applicationDomain));
        body.put(AuthenticationBackend.APPLICATION_PARAMETER, Collections.singletonList(applicationName));
        body.put(AuthenticationBackend.TOKEN_TYPE_PARAMETER, Collections.singletonList(tokenType.getParameter()));
        return body;
    }

    private Map> createUserStoreCombinedBody(
            final String applicationName,
            final String applicationDomain,
            final TokenType tokenType,
            final String userStoreDomain,
            final String userStoreName
    ) {
        final Map> body = createBaseCombinedBody(applicationName, applicationDomain, tokenType);
        body.put(AuthenticationBackend.USERSTORE_DOMAIN_PARAMETER, Collections.singletonList(userStoreDomain));
        body.put(AuthenticationBackend.USERSTORE_NAME_PARAMETER, Collections.singletonList(userStoreName));
        return body;
    }

    private  TokenProxy insertToken(final AuthenticationToken token) {
        try {
            return tokenRepository.insert(token);
        } catch (final IOException e) {
            throw new TokenRepositoryException(e);
        }
    }

    private  AuthenticationToken getToken(final TokenProxy tokenProxy) {
        try {
            return tokenRepository.get(tokenProxy);
        } catch (final IOException e) {
            throw new TokenRepositoryException(e);
        }
    }

    private  AuthenticationToken parseToken(final Response response, final E entityType, final T tokenType) {
        try {
            final TokenResponse tokenResponse = objectMapper.readValue(response.getBody().in(), TOKEN_TYPE_REFERENCE);
            return tokenResponse.getToken().buildToken(entityType, tokenType);
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }

    private  T parseTokenInformation(final Response response, final TypeReference> typeReference) {
        try {
            final TokenResponse tokenResponse = objectMapper.readValue(response.getBody().in(), typeReference);
            return tokenResponse.getToken();
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy