com.hp.autonomy.hod.client.api.authentication.AuthenticationServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-hod-client Show documentation
Show all versions of java-hod-client Show documentation
Java Client for communicating with HP Haven OnDemand
/*
* 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);
}
}
}