/** * Allows users to revoke an OAuth2 application. This will remove their consent and revoke any * access and refresh tokens with a matching client id. * * @param context The request context. * @param resourceId The id of the OAuth2 client. * @return A promise of the removed application. */ @Delete public Promise<ResourceResponse, ResourceException> deleteInstance( Context context, String resourceId) { String userId = contextHelper.getUserId(context); String realm = contextHelper.getRealm(context); debug.message("Revoking access to OAuth2 client {} for user {}", resourceId, userId); try { oAuth2ProviderSettingsFactory.get(context).revokeConsent(userId, resourceId); QueryFilter<CoreTokenField> queryFilter = and(getQueryFilter(userId, realm), equalTo(CLIENT_ID.getField(), resourceId)); JsonValue tokens = tokenStore.query(queryFilter); if (tokens.asCollection().isEmpty()) { return new org.forgerock.json.resource.NotFoundException().asPromise(); } for (JsonValue token : tokens) { String tokenId = getAttributeValue(token, ID.getOAuthField()); debug.message( "Removing OAuth2 token {} with client {} for user {}", tokenId, resourceId, userId); tokenStore.delete(tokenId); } return getResourceResponse(context, resourceId, tokens).asPromise(); } catch (CoreTokenException | InvalidClientException | NotFoundException | ServerException e) { debug.message( "Failed to revoke access to OAuth2 client {} for user {}", resourceId, userId, e); return new InternalServerErrorException(e).asPromise(); } catch (InternalServerErrorException e) { debug.message( "Failed to revoke access to OAuth2 client {} for user {}", resourceId, userId, e); return e.asPromise(); } }
/** * Allows users to query OAuth2 applications that they have given their consent access to and that * have active access and/or refresh tokens. * * <p>Applications consist of an id, a name (the client id), a set of scopes and an expiry time. * The scopes field is the union of the scopes of the individual access/refresh tokens. The expiry * time is the time when the last access/refresh token will expire, or null if the server is * configured to allow tokens to be refreshed indefinitely. * * @param context The request context. * @param queryHandler The query handler. * @param request Unused but necessary for used of the {@link @Query} annotation. * @return A promise of a query response. */ @Query public Promise<QueryResponse, ResourceException> query( Context context, QueryResourceHandler queryHandler, QueryRequest request) { String userId = contextHelper.getUserId(context); String realm = contextHelper.getRealm(context); try { QueryFilter<CoreTokenField> queryFilter = getQueryFilter(userId, realm); JsonValue tokens = tokenStore.query(queryFilter); Map<String, Set<JsonValue>> applicationTokensMap = new HashMap<>(); for (JsonValue token : tokens) { String clientId = getAttributeValue(token, CLIENT_ID.getOAuthField()); Set<JsonValue> applicationTokens = applicationTokensMap.get(clientId); if (applicationTokens == null) { applicationTokens = new HashSet<>(); applicationTokensMap.put(clientId, applicationTokens); } applicationTokens.add(token); } for (Map.Entry<String, Set<JsonValue>> applicationTokens : applicationTokensMap.entrySet()) { ResourceResponse resource = getResourceResponse(context, applicationTokens.getKey(), applicationTokens.getValue()); queryHandler.handleResource(resource); } return Promises.newResultPromise(Responses.newQueryResponse()); } catch (CoreTokenException | ServerException | InvalidClientException | NotFoundException e) { debug.message("Failed to query OAuth2 clients for user {}", userId, e); return new InternalServerErrorException(e).asPromise(); } catch (InternalServerErrorException e) { debug.message("Failed to query OAuth2 clients for user {}", userId, e); return e.asPromise(); } }