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);
}
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);
}
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);
}
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;
}
}
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;
}
}
Aggregations