use of org.codice.ddf.security.token.storage.api.TokenInformation.TokenEntry 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.TokenEntry in project ddf by codice.
the class OAuthPlugin method process.
/**
* Verifies that a source configured to use OAuth has a valid access token to process and that the
* user has authorized the use of their data against this source.
*
* @param source source being queried
* @param input query request
* @throws OAuthPluginException if the user's access token is not available or if the source is
* not authorized
* @throws StopProcessingException for errors not related to OAuth
*/
@Override
public QueryRequest process(Source source, QueryRequest input) throws StopProcessingException {
OAuthFederatedSource oauthSource = getSource(source);
if (oauthSource == null) {
return input;
}
Object securityAssertion = input.getProperties().get(SECURITY_SUBJECT);
if (!(securityAssertion instanceof Subject)) {
LOGGER.warn("The user's subject is not available.");
throw new StopProcessingException("The user's subject is not available.");
}
Subject subject = (Subject) securityAssertion;
Session session = subject.getSession(false);
if (session == null) {
LOGGER.warn("The user's session is not available.");
throw new StopProcessingException("The user's session is not available.");
}
String sessionId = (String) session.getId();
if (sessionId == null) {
LOGGER.warn("The user's session ID is not available.");
throw new StopProcessingException("The user's session ID is not available.");
}
OIDCProviderMetadata metadata;
try {
metadata = OIDCProviderMetadata.parse(resourceRetriever.retrieveResource(new URL(oauthSource.getOauthDiscoveryUrl())).getContent());
} catch (OAuthServiceException | IOException | ParseException e) {
LOGGER.error("Unable to retrieve OAuth provider's metadata for the {} source.", oauthSource.getId());
throw new StopProcessingException("Unable to retrieve OAuth provider's metadata.");
}
TokenEntry tokenEntry = tokenStorage.read(sessionId, oauthSource.getId());
if (tokenEntry == null) {
// See if the user already logged in to the OAuth provider for a different source
findExistingTokens(oauthSource, sessionId, metadata);
throw createNoAuthException(oauthSource, sessionId, metadata, "the user's tokens were not found.");
}
// an outdated token)
if (!oauthSource.getOauthDiscoveryUrl().equals(tokenEntry.getDiscoveryUrl())) {
// the discoveryUrl is different from the one stored - the user must login
tokenStorage.delete(sessionId, oauthSource.getId());
findExistingTokens(oauthSource, sessionId, metadata);
throw createNoAuthException(oauthSource, sessionId, metadata, "the oauth provider information has been changed and is different from the one stored.");
}
verifyAccessToken(oauthSource, sessionId, tokenEntry, metadata);
return input;
}
use of org.codice.ddf.security.token.storage.api.TokenInformation.TokenEntry 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.TokenEntry in project ddf by codice.
the class OAuthSecurityImpl method setUserTokenOnClient.
/**
* Gets the user's access token from the token storage to set it to the OAUTH header. Used when a
* source is configured to use Authentication Code flow/grant.
*
* @param client Non-null client to set the access token on.
* @param subject subject used to get the session ID
* @param sourceId the id of the source using OAuth needed to get the correct tokens
*/
@Override
public void setUserTokenOnClient(Client client, Subject subject, String sourceId) {
if (client == null || subject == null || Strings.isBlank(sourceId)) {
return;
}
Session session = subject.getSession(false);
if (session == null) {
LOGGER.warn("The user's session is not available.");
return;
}
String sessionId = (String) session.getId();
if (sessionId == null) {
LOGGER.warn("The user's session ID is not available.");
return;
}
TokenInformation.TokenEntry tokenEntry = tokenStorage.read(sessionId, sourceId);
if (tokenEntry == null) {
return;
}
LOGGER.debug(ADDING_TOKEN);
client.header(OAUTH, BEARER + tokenEntry.getAccessToken());
}
use of org.codice.ddf.security.token.storage.api.TokenInformation.TokenEntry in project ddf by codice.
the class OAuthSecurityImpl method getValidToken.
/**
* Attempts to get an unexpired access token from the token storage or by making a request to the
* OAuth provider.
*
* @param id The ID used when retrieving tokens from the token storage
* @param sourceId The ID of the source using OAuth needed to get the correct tokens
* @param clientId The client ID registered with the OAuth provider
* @param clientSecret The client secret registered with the OAuth provider
* @param discoveryUrl The discovery URL of the OAuth provider
* @param grantType The grant type used if a request is sent to get a new token
* @param queryParameters Parameters used if a request is sent to get a new token
* @return an access token or null if all means of getting one fail
*/
private String getValidToken(String id, String sourceId, String clientId, String clientSecret, String discoveryUrl, String grantType, Map<String, String> queryParameters) {
TokenEntry tokenEntry = tokenStorage.read(id, sourceId);
if (tokenEntry != null && discoveryUrl.equalsIgnoreCase(tokenEntry.getDiscoveryUrl()) && !isExpired(tokenEntry.getAccessToken())) {
return tokenEntry.getAccessToken();
}
OIDCProviderMetadata metadata;
try {
metadata = OIDCProviderMetadata.parse(resourceRetriever.retrieveResource(new URL(discoveryUrl)).getContent());
} catch (IOException | ParseException e) {
LOGGER.error("Unable to retrieve OAuth provider's metadata.", e);
return null;
}
if (tokenEntry != null && discoveryUrl.equalsIgnoreCase(tokenEntry.getDiscoveryUrl()) && isExpired(tokenEntry.getAccessToken()) && !isExpired(tokenEntry.getRefreshToken())) {
// refresh token
return refreshToken(id, sourceId, clientId, clientSecret, discoveryUrl, tokenEntry.getRefreshToken(), metadata);
}
// Make a call to get a token
String encodedClientIdSecret = Base64.getEncoder().encodeToString((clientId + ":" + clientSecret).getBytes(UTF_8));
return getNewAccessToken(id, sourceId, encodedClientIdSecret, discoveryUrl, grantType, queryParameters, metadata);
}
Aggregations