Search in sources :

Example 1 with TokenInformation

use of org.codice.ddf.security.token.storage.api.TokenInformation 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 2 with TokenInformation

use of org.codice.ddf.security.token.storage.api.TokenInformation in project ddf by codice.

the class FileSystemTokenStorage method delete.

/**
 * Removes tokens associated with the given ID for the specified source
 *
 * @param id the ID associated with the tokens
 * @param sourceId the ID for the source the tokens are going to be used against
 * @return an HTTP status code
 */
@Override
public int delete(String id, String sourceId) {
    LOGGER.trace("Delete: Deleting a Token Storage entry.");
    TokenInformation tokenInformation = read(id);
    if (tokenInformation == null) {
        return SC_OK;
    }
    TokenEntry tokenEntry = tokenInformation.getTokenEntries().get(sourceId);
    if (tokenEntry == null) {
        return SC_OK;
    }
    Path contentItemPath = Paths.get(baseDirectory.toAbsolutePath().toString(), tokenInformation.getId());
    if (tokenInformation.getTokenEntries().size() == 1) {
        // delete file
        try {
            Files.delete(contentItemPath);
            return SC_OK;
        } catch (IOException e) {
            LOGGER.debug("Error deleting token file.", e);
            return SC_INTERNAL_SERVER_ERROR;
        }
    }
    String json = TokenInformationUtil.removeTokens(tokenInformation.getTokenJson(), sourceId);
    return writeToFile(contentItemPath, json);
}
Also used : Path(java.nio.file.Path) TokenEntry(org.codice.ddf.security.token.storage.api.TokenInformation.TokenEntry) TokenInformation(org.codice.ddf.security.token.storage.api.TokenInformation) IOException(java.io.IOException)

Example 3 with TokenInformation

use of org.codice.ddf.security.token.storage.api.TokenInformation in project ddf by codice.

the class FileSystemTokenStorage method create.

/**
 * Stores a user's or client's access token. If it's a new user or client, creates a new entry.
 * Otherwise, updates the existing data.
 *
 * @param id the ID used to store the tokens
 * @param sourceId the ID of the source the tokens are going to be used against
 * @param accessToken the access token
 * @param refreshToken the refresh token
 * @param discoveryUrl the metadata url of the OAuth provider protecting the source
 * @return an HTTP status code
 */
@Override
public int create(String id, String sourceId, String accessToken, String refreshToken, String discoveryUrl) {
    LOGGER.trace("Create: Updating a Token Storage entry.");
    String fileName;
    String json;
    TokenInformation tokenInformation = read(id);
    if (tokenInformation == null) {
        // create new entry
        fileName = hashId(id);
        json = TokenInformationUtil.getJson(sourceId, accessToken, refreshToken, discoveryUrl);
    } else {
        // update existing
        fileName = tokenInformation.getId();
        json = TokenInformationUtil.getJson(tokenInformation.getTokenJson(), sourceId, accessToken, refreshToken, discoveryUrl);
    }
    Path contentItemPath = Paths.get(baseDirectory.toAbsolutePath().toString(), fileName);
    return writeToFile(contentItemPath, json);
}
Also used : Path(java.nio.file.Path) TokenInformation(org.codice.ddf.security.token.storage.api.TokenInformation)

Example 4 with TokenInformation

use of org.codice.ddf.security.token.storage.api.TokenInformation 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 5 with TokenInformation

use of org.codice.ddf.security.token.storage.api.TokenInformation 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

TokenInformation (org.codice.ddf.security.token.storage.api.TokenInformation)6 QueryRequest (ddf.catalog.operation.QueryRequest)3 OAuthPluginException (ddf.catalog.plugin.OAuthPluginException)3 OAuthFederatedSource (ddf.catalog.source.OAuthFederatedSource)3 Subject (ddf.security.Subject)3 Map (java.util.Map)3 Test (org.junit.Test)3 ImmutableMap (com.google.common.collect.ImmutableMap)2 IOException (java.io.IOException)2 Path (java.nio.file.Path)2 Date (java.util.Date)2 TokenEntry (org.codice.ddf.security.token.storage.api.TokenInformation.TokenEntry)2 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 Gson (com.google.gson.Gson)1 GsonBuilder (com.google.gson.GsonBuilder)1 DefaultResourceRetriever (com.nimbusds.jose.util.DefaultResourceRetriever)1 ResourceRetriever (com.nimbusds.jose.util.ResourceRetriever)1 ParseException (com.nimbusds.oauth2.sdk.ParseException)1 Scope (com.nimbusds.oauth2.sdk.Scope)1