Search in sources :

Example 1 with OAuthPluginException

use of ddf.catalog.plugin.OAuthPluginException in project ddf by codice.

the class AbstractCatalogService method getDocument.

@Override
public BinaryContent getDocument(String encodedSourceId, String encodedId, String transformerParam, URI absolutePath, MultivaluedMap<String, String> queryParameters, HttpServletRequest httpRequest) throws CatalogServiceException, DataUsageLimitExceededException, InternalServerErrorException {
    QueryResponse queryResponse;
    Metacard card = null;
    LOGGER.trace("GET");
    if (encodedId != null) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Got id: {}", LogSanitizer.sanitize(encodedId));
            LOGGER.debug("Got service: {}", LogSanitizer.sanitize(transformerParam));
            LOGGER.debug("Map of query parameters: \n{}", LogSanitizer.sanitize(queryParameters));
        }
        Map<String, Serializable> convertedMap = convert(queryParameters);
        convertedMap.put("url", absolutePath.toString());
        LOGGER.debug("Map converted, retrieving product.");
        // default to xml if no transformer specified
        try {
            String id = URLDecoder.decode(encodedId, CharEncoding.UTF_8);
            String transformer = DEFAULT_METACARD_TRANSFORMER;
            if (transformerParam != null) {
                transformer = transformerParam;
            }
            Filter filter = getFilterBuilder().attribute(Metacard.ID).is().equalTo().text(id);
            Collection<String> sources = null;
            if (encodedSourceId != null) {
                String sourceid = URLDecoder.decode(encodedSourceId, CharEncoding.UTF_8);
                sources = new ArrayList<>();
                sources.add(sourceid);
            }
            QueryRequestImpl request = new QueryRequestImpl(new QueryImpl(filter), sources);
            request.setProperties(convertedMap);
            queryResponse = catalogFramework.query(request, null);
            // pull the metacard out of the blocking queue
            List<Result> results = queryResponse.getResults();
            // return null if timeout elapsed)
            if (results != null && !results.isEmpty()) {
                card = results.get(0).getMetacard();
            }
            if (card == null) {
                return null;
            }
            // Check for Range header set the value in the map appropriately so that the
            // catalogFramework
            // can take care of the skipping
            long bytesToSkip = getRangeStart(httpRequest);
            if (bytesToSkip > 0) {
                LOGGER.debug("Bytes to skip: {}", bytesToSkip);
                convertedMap.put(BYTES_TO_SKIP, bytesToSkip);
            }
            LOGGER.debug("Calling transform.");
            final BinaryContent content = catalogFramework.transform(card, transformer, convertedMap);
            LOGGER.debug("Read and transform complete, preparing response.");
            return content;
        } catch (FederationException e) {
            String exceptionMessage = "READ failed due to unexpected exception: ";
            LOGGER.info(exceptionMessage, e);
            throw new InternalServerErrorException(exceptionMessage);
        } catch (CatalogTransformerException e) {
            String exceptionMessage = "Unable to transform Metacard.  Try different transformer: ";
            LOGGER.info(exceptionMessage, e);
            throw new InternalServerErrorException(exceptionMessage);
        } catch (SourceUnavailableException e) {
            String exceptionMessage = "Cannot obtain query results because source is unavailable: ";
            LOGGER.info(exceptionMessage, e);
            throw new InternalServerErrorException(exceptionMessage);
        } catch (UnsupportedQueryException e) {
            String errorMessage = "Specified query is unsupported.  Change query and resubmit: ";
            LOGGER.info(errorMessage, e);
            throw new CatalogServiceException(errorMessage);
        } catch (DataUsageLimitExceededException e) {
            String errorMessage = "Unable to process request. Data usage limit exceeded: ";
            LOGGER.debug(errorMessage, e);
            throw new DataUsageLimitExceededException(errorMessage);
        } catch (OAuthPluginException e) {
            Map<String, String> parameters = e.getParameters();
            String url = constructUrl(httpRequest, e.getBaseUrl(), parameters);
            if (url != null) {
                parameters.put(REDIRECT_URI, url);
                throw new OAuthPluginException(e.getSourceId(), url, e.getBaseUrl(), parameters, e.getErrorType());
            }
            throw e;
        // The catalog framework will throw this if any of the transformers blow up.
        // We need to catch this exception here or else execution will return to CXF and
        // we'll lose this message and end up with a huge stack trace in a GUI or whatever
        // else is connected to this endpoint
        } catch (RuntimeException | UnsupportedEncodingException e) {
            String exceptionMessage = "Unknown error occurred while processing request.";
            LOGGER.info(exceptionMessage, e);
            throw new InternalServerErrorException(exceptionMessage);
        }
    } else {
        throw new CatalogServiceException("No ID specified.");
    }
}
Also used : SourceUnavailableException(ddf.catalog.source.SourceUnavailableException) Serializable(java.io.Serializable) UnsupportedQueryException(ddf.catalog.source.UnsupportedQueryException) CatalogTransformerException(ddf.catalog.transform.CatalogTransformerException) BinaryContent(ddf.catalog.data.BinaryContent) Result(ddf.catalog.data.Result) QueryImpl(ddf.catalog.operation.impl.QueryImpl) DataUsageLimitExceededException(ddf.catalog.resource.DataUsageLimitExceededException) CatalogServiceException(org.codice.ddf.rest.api.CatalogServiceException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) FederationException(ddf.catalog.federation.FederationException) Metacard(ddf.catalog.data.Metacard) OAuthPluginException(ddf.catalog.plugin.OAuthPluginException) Filter(org.opengis.filter.Filter) QueryResponse(ddf.catalog.operation.QueryResponse) QueryRequestImpl(ddf.catalog.operation.impl.QueryRequestImpl) InternalServerErrorException(javax.ws.rs.InternalServerErrorException) Map(java.util.Map) HashMap(java.util.HashMap) MultivaluedMap(javax.ws.rs.core.MultivaluedMap)

Example 2 with OAuthPluginException

use of ddf.catalog.plugin.OAuthPluginException in project ddf by codice.

the class OAuthPlugin method findExistingTokens.

/**
 * Looks through the user's tokens to see if there are tokens from a different source connected to
 * the same OAuth provider. The discovery URLs need to match. If a match is found an authorize
 * source exception will be thrown so the user can authorize to query the new source instead of
 * logging in.
 */
private void findExistingTokens(OAuthFederatedSource oauthSource, String sessionId, OIDCProviderMetadata metadata) throws StopProcessingException {
    TokenInformation tokenInformation = tokenStorage.read(sessionId);
    if (tokenInformation == null || !tokenInformation.getDiscoveryUrls().contains(oauthSource.getOauthDiscoveryUrl())) {
        return;
    }
    // Verify that an unexpired token exists
    List<TokenInformation.TokenEntry> matchingTokenEntries = tokenInformation.getTokenEntries().entrySet().stream().filter(entry -> !entry.getKey().equals(oauthSource.getId())).filter(entry -> entry.getValue().getDiscoveryUrl().equals(oauthSource.getOauthDiscoveryUrl())).map(Map.Entry::getValue).collect(Collectors.toList());
    TokenInformation.TokenEntry tokenEntry = matchingTokenEntries.stream().filter(entry -> entry.getAccessToken() != null).filter(entry -> !isExpired(entry.getAccessToken())).findAny().orElse(null);
    if (tokenEntry == null) {
        // does one with a valid refresh token exist
        tokenEntry = matchingTokenEntries.stream().filter(entry -> entry.getRefreshToken() != null).filter(entry -> !isExpired(entry.getRefreshToken())).findAny().orElse(null);
        if (tokenEntry == null) {
            return;
        }
        refreshTokens(tokenEntry.getRefreshToken(), oauthSource, sessionId, metadata);
    }
    LOGGER.debug("Unable to process query. The user needs to authorize to query the {} source.", oauthSource.getId());
    Map<String, String> parameters = new HashMap<>();
    parameters.put(SOURCE_ID, oauthSource.getId());
    parameters.put(DISCOVERY_URL, oauthSource.getOauthDiscoveryUrl());
    throw new OAuthPluginException(oauthSource.getId(), buildUrl(AUTHORIZE_SOURCE_ENDPOINT, parameters), AUTHORIZE_SOURCE_ENDPOINT, parameters, AUTH_SOURCE);
}
Also used : STATE(org.codice.ddf.security.token.storage.api.TokenStorage.STATE) Arrays(java.util.Arrays) URL(java.net.URL) URISyntaxException(java.net.URISyntaxException) RefreshTokenGrant(org.apache.cxf.rs.security.oauth2.grants.refresh.RefreshTokenGrant) LoggerFactory(org.slf4j.LoggerFactory) DefaultResourceRetriever(com.nimbusds.jose.util.DefaultResourceRetriever) Session(org.apache.shiro.session.Session) ClientAccessToken(org.apache.cxf.rs.security.oauth2.common.ClientAccessToken) GsonBuilder(com.google.gson.GsonBuilder) NO_AUTH(ddf.catalog.plugin.OAuthPluginException.ErrorType.NO_AUTH) OAuthClientUtils(org.apache.cxf.rs.security.oauth2.client.OAuthClientUtils) OAuthFederatedSource(ddf.catalog.source.OAuthFederatedSource) EXPIRES_AT(org.codice.ddf.security.token.storage.api.TokenStorage.EXPIRES_AT) Gson(com.google.gson.Gson) OidcTokenValidator(org.codice.ddf.security.oidc.validator.OidcTokenValidator) Map(java.util.Map) Bundle(org.osgi.framework.Bundle) TokenInformation(org.codice.ddf.security.token.storage.api.TokenInformation) ServiceReference(org.osgi.framework.ServiceReference) Consumer(org.apache.cxf.rs.security.oauth2.client.Consumer) AccessToken(com.nimbusds.oauth2.sdk.token.AccessToken) OAuthPluginException(ddf.catalog.plugin.OAuthPluginException) InvalidSyntaxException(org.osgi.framework.InvalidSyntaxException) URIBuilder(org.apache.http.client.utils.URIBuilder) Collection(java.util.Collection) UUID(java.util.UUID) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) BundleContext(org.osgi.framework.BundleContext) Base64(java.util.Base64) List(java.util.List) OAuthServiceException(org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException) HashMap(java.util.HashMap) TokenEntry(org.codice.ddf.security.token.storage.api.TokenInformation.TokenEntry) SECRET(org.codice.ddf.security.token.storage.api.TokenStorage.SECRET) SOURCE_ID(org.codice.ddf.security.token.storage.api.TokenStorage.SOURCE_ID) Source(ddf.catalog.source.Source) DISCOVERY_URL(org.codice.ddf.security.token.storage.api.TokenStorage.DISCOVERY_URL) QueryRequest(ddf.catalog.operation.QueryRequest) AUTH_SOURCE(ddf.catalog.plugin.OAuthPluginException.ErrorType.AUTH_SOURCE) ParseException(com.nimbusds.oauth2.sdk.ParseException) CLIENT_ID(org.codice.ddf.security.token.storage.api.TokenStorage.CLIENT_ID) GsonTypeAdapters(org.codice.gsonsupport.GsonTypeAdapters) PreFederatedQueryPlugin(ddf.catalog.plugin.PreFederatedQueryPlugin) Logger(org.slf4j.Logger) SystemBaseUrl(org.codice.ddf.configuration.SystemBaseUrl) OIDCProviderMetadata(com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata) MalformedURLException(java.net.MalformedURLException) WebClient(org.apache.cxf.jaxrs.client.WebClient) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) Scope(com.nimbusds.oauth2.sdk.Scope) StopProcessingException(ddf.catalog.plugin.StopProcessingException) Subject(ddf.security.Subject) IOException(java.io.IOException) SECURITY_SUBJECT(ddf.security.SecurityConstants.SECURITY_SUBJECT) OidcValidationException(org.codice.ddf.security.oidc.validator.OidcValidationException) MAP_STRING_TO_OBJECT_TYPE(org.codice.gsonsupport.GsonTypeAdapters.MAP_STRING_TO_OBJECT_TYPE) ResourceRetriever(com.nimbusds.jose.util.ResourceRetriever) SC_OK(org.apache.http.HttpStatus.SC_OK) ChronoUnit(java.time.temporal.ChronoUnit) TokenStorage(org.codice.ddf.security.token.storage.api.TokenStorage) VisibleForTesting(com.google.common.annotations.VisibleForTesting) AccessTokenGrant(org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant) TypelessAccessToken(com.nimbusds.oauth2.sdk.token.TypelessAccessToken) FrameworkUtil(org.osgi.framework.FrameworkUtil) TokenEntry(org.codice.ddf.security.token.storage.api.TokenInformation.TokenEntry) OAuthPluginException(ddf.catalog.plugin.OAuthPluginException) TokenEntry(org.codice.ddf.security.token.storage.api.TokenInformation.TokenEntry) HashMap(java.util.HashMap) TokenInformation(org.codice.ddf.security.token.storage.api.TokenInformation) Map(java.util.Map) HashMap(java.util.HashMap)

Example 3 with OAuthPluginException

use of ddf.catalog.plugin.OAuthPluginException in project ddf by codice.

the class OAuthPluginTest method testNoStoredTokensExistingTokenUnderDifferentSourceExpiredTokens.

@Test(expected = OAuthPluginException.class)
public void testNoStoredTokensExistingTokenUnderDifferentSourceExpiredTokens() throws Exception {
    OAuthFederatedSource source = oauthPlugin.oauthSource;
    Subject subject = getSubject();
    QueryRequest input = mock(QueryRequest.class);
    when(input.getProperties()).thenReturn(ImmutableMap.of(SECURITY_SUBJECT, subject));
    String accessToken = getAccessTokenBuilder().withExpiresAt(new Date(Instant.now().minus(1, ChronoUnit.MINUTES).toEpochMilli())).sign(validAlgorithm);
    String refreshToken = getRefreshTokenBuilder().withExpiresAt(new Date(Instant.now().minus(1, ChronoUnit.MINUTES).toEpochMilli())).sign(validAlgorithm);
    TokenInformation.TokenEntry tokenEntry = new TokenInformationImpl.TokenEntryImpl(accessToken, refreshToken, METADATA_ENDPOINT);
    TokenInformation tokenInformation = mock(TokenInformation.class);
    when(tokenInformation.getDiscoveryUrls()).thenReturn(Collections.singleton(METADATA_ENDPOINT));
    when(tokenInformation.getTokenEntries()).thenReturn(Collections.singletonMap("OS", tokenEntry));
    Map<String, Map<String, Object>> stateMap = mock(Map.class);
    when(tokenStorage.getStateMap()).thenReturn(stateMap);
    when(tokenStorage.read(SESSION, SOURCE_ID)).thenReturn(null);
    when(tokenStorage.read(SESSION)).thenReturn(tokenInformation);
    try {
        oauthPlugin.process(source, input);
    } catch (OAuthPluginException e) {
        assertEquals(e.getSourceId(), CSW_SOURCE);
        assertEquals(e.getErrorType().getStatusCode(), 401);
        ArgumentCaptor<Map<String, Object>> captor = ArgumentCaptor.forClass(Map.class);
        verify(stateMap, times(1)).put(anyString(), captor.capture());
        assertUrl(e, captor.getValue());
        throw e;
    }
}
Also used : OAuthFederatedSource(ddf.catalog.source.OAuthFederatedSource) ArgumentCaptor(org.mockito.ArgumentCaptor) QueryRequest(ddf.catalog.operation.QueryRequest) TokenInformation(org.codice.ddf.security.token.storage.api.TokenInformation) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Subject(ddf.security.Subject) Date(java.util.Date) OAuthPluginException(ddf.catalog.plugin.OAuthPluginException) JSONObject(net.minidev.json.JSONObject) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) Test(org.junit.Test)

Example 4 with OAuthPluginException

use of ddf.catalog.plugin.OAuthPluginException in project ddf by codice.

the class OAuthPluginTest method testDifferentDiscoveryUrl.

@Test(expected = OAuthPluginException.class)
public void testDifferentDiscoveryUrl() throws Exception {
    OAuthFederatedSource source = oauthPlugin.oauthSource;
    Subject subject = getSubject();
    QueryRequest input = mock(QueryRequest.class);
    when(input.getProperties()).thenReturn(ImmutableMap.of(SECURITY_SUBJECT, subject));
    Map<String, Map<String, Object>> stateMap = mock(Map.class);
    String accessToken = getAccessTokenBuilder().sign(validAlgorithm);
    TokenInformation.TokenEntry tokenEntry = new TokenInformationImpl.TokenEntryImpl(accessToken, "refresh_token", "http://example.com");
    when(tokenStorage.read(SESSION, CSW_SOURCE)).thenReturn(tokenEntry);
    when(tokenStorage.getStateMap()).thenReturn(stateMap);
    try {
        oauthPlugin.process(source, input);
    } catch (OAuthPluginException e) {
        verify(tokenStorage, times(1)).delete(SESSION, CSW_SOURCE);
        verify(tokenStorage, times(1)).getStateMap();
        ArgumentCaptor<Map<String, Object>> captor = ArgumentCaptor.forClass(Map.class);
        verify(stateMap, times(1)).put(anyString(), captor.capture());
        assertUrl(e, captor.getValue());
        throw e;
    }
}
Also used : OAuthFederatedSource(ddf.catalog.source.OAuthFederatedSource) OAuthPluginException(ddf.catalog.plugin.OAuthPluginException) ArgumentCaptor(org.mockito.ArgumentCaptor) QueryRequest(ddf.catalog.operation.QueryRequest) TokenInformation(org.codice.ddf.security.token.storage.api.TokenInformation) JSONObject(net.minidev.json.JSONObject) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) Subject(ddf.security.Subject) Test(org.junit.Test)

Example 5 with OAuthPluginException

use of ddf.catalog.plugin.OAuthPluginException in project ddf by codice.

the class OAuthPluginTest method testNoStoredTokensButExistingUnderDifferentSource.

@Test(expected = OAuthPluginException.class)
public void testNoStoredTokensButExistingUnderDifferentSource() throws Exception {
    OAuthFederatedSource source = oauthPlugin.oauthSource;
    Subject subject = getSubject();
    QueryRequest input = mock(QueryRequest.class);
    when(input.getProperties()).thenReturn(ImmutableMap.of(SECURITY_SUBJECT, subject));
    String accessToken = getAccessTokenBuilder().withExpiresAt(new Date(Instant.now().plus(1, ChronoUnit.MINUTES).toEpochMilli())).sign(validAlgorithm);
    TokenInformation.TokenEntry tokenEntry = new TokenInformationImpl.TokenEntryImpl(accessToken, "myRefreshToken", METADATA_ENDPOINT);
    TokenInformation tokenInformation = mock(TokenInformation.class);
    when(tokenInformation.getDiscoveryUrls()).thenReturn(Collections.singleton(METADATA_ENDPOINT));
    when(tokenInformation.getTokenEntries()).thenReturn(Collections.singletonMap("OS", tokenEntry));
    when(tokenStorage.read(SESSION, SOURCE_ID)).thenReturn(null);
    when(tokenStorage.read(SESSION)).thenReturn(tokenInformation);
    try {
        oauthPlugin.process(source, input);
    } catch (OAuthPluginException e) {
        assertEquals(e.getSourceId(), CSW_SOURCE);
        assertEquals(e.getErrorType().getStatusCode(), 412);
        String url = e.getUrl();
        Map<String, String> urlParams = URLEncodedUtils.parse(new URI(url), StandardCharsets.UTF_8).stream().collect(Collectors.toMap(NameValuePair::getName, NameValuePair::getValue));
        assertEquals(urlParams.get(SOURCE_ID), CSW_SOURCE);
        assertEquals(urlParams.get(DISCOVERY_URL), METADATA_ENDPOINT);
        throw e;
    }
}
Also used : OAuthFederatedSource(ddf.catalog.source.OAuthFederatedSource) NameValuePair(org.apache.http.NameValuePair) OAuthPluginException(ddf.catalog.plugin.OAuthPluginException) QueryRequest(ddf.catalog.operation.QueryRequest) TokenInformation(org.codice.ddf.security.token.storage.api.TokenInformation) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) URI(java.net.URI) Subject(ddf.security.Subject) Date(java.util.Date) Test(org.junit.Test)

Aggregations

OAuthPluginException (ddf.catalog.plugin.OAuthPluginException)9 Map (java.util.Map)7 QueryRequest (ddf.catalog.operation.QueryRequest)6 OAuthFederatedSource (ddf.catalog.source.OAuthFederatedSource)6 Subject (ddf.security.Subject)6 TokenInformation (org.codice.ddf.security.token.storage.api.TokenInformation)6 ImmutableMap (com.google.common.collect.ImmutableMap)5 Test (org.junit.Test)5 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)5 Date (java.util.Date)4 JSONObject (net.minidev.json.JSONObject)4 ArgumentCaptor (org.mockito.ArgumentCaptor)4 Response (javax.ws.rs.core.Response)3 BinaryContent (ddf.catalog.data.BinaryContent)2 FederationException (ddf.catalog.federation.FederationException)2 QueryResponse (ddf.catalog.operation.QueryResponse)2 DataUsageLimitExceededException (ddf.catalog.resource.DataUsageLimitExceededException)2 UnsupportedQueryException (ddf.catalog.source.UnsupportedQueryException)2 HashMap (java.util.HashMap)2 Form (javax.ws.rs.core.Form)2