Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show unrestricted scopes into well-known endpoint #628

Merged
merged 12 commits into from
Apr 10, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,44 @@



import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;

import it.infn.mw.iam.core.web.wellknown.IamWellKnownInfoProvider;

@Configuration
@EnableCaching
public class CacheConfig {

private static final Logger LOG = LoggerFactory.getLogger(CacheConfig.class);

@Autowired
CacheManager cacheManager;

@Scheduled(fixedDelay = 5, timeUnit = TimeUnit.MINUTES)
public void evictWellKnownCache() {

Cache getCacheForWellKnown = cacheManager.getCache(IamWellKnownInfoProvider.CACHE_KEY);
federicaagostini marked this conversation as resolved.
Show resolved Hide resolved

if (getCacheForWellKnown != null) {
getCacheForWellKnown.clear();
LOG.debug("well-known config cache evicted");
}
}

federicaagostini marked this conversation as resolved.
Show resolved Hide resolved
@Bean
public CacheManager cacheManager() {

return new ConcurrentMapCacheManager(IamWellKnownInfoProvider.CACHE_KEY);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.mitre.jwt.encryption.service.JWTEncryptionAndDecryptionService;
import org.mitre.oauth2.model.PKCEAlgorithm;
Expand All @@ -31,11 +30,7 @@
import org.mitre.oauth2.web.IntrospectionEndpoint;
import org.mitre.oauth2.web.RevocationEndpoint;
import org.mitre.openid.connect.web.UserInfoEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import com.nimbusds.jose.Algorithm;
Expand All @@ -50,8 +45,6 @@
@Service
public class IamWellKnownInfoProvider implements WellKnownInfoProvider {

private static final Logger LOG = LoggerFactory.getLogger(IamWellKnownInfoProvider.class);

public static final String CACHE_KEY = "well-known-config";

public static final String AUTHORIZE_ENDPOINT = "authorize";
Expand Down Expand Up @@ -112,7 +105,7 @@ public class IamWellKnownInfoProvider implements WellKnownInfoProvider {
private final String deviceAuthorizationEndpoint;
private final String aboutEndpoint;
private Set<String> supportedScopes;


public IamWellKnownInfoProvider(IamProperties properties,
JWTEncryptionAndDecryptionService encService, SystemScopeService scopeService) {
Expand Down Expand Up @@ -182,7 +175,7 @@ public Map<String, Object> getWellKnownInfo() {
result.put("jwks_uri", jwkEndpoint);
result.put("registration_endpoint", clientRegistrationEndpoint);

result.put("introspection_endpoint", introspectionEndpoint );
result.put("introspection_endpoint", introspectionEndpoint);
result.put("revocation_endpoint", revocationEndpoint);
result.put("device_authorization_endpoint", deviceAuthorizationEndpoint);

Expand Down Expand Up @@ -220,15 +213,10 @@ public Map<String, Object> getWellKnownInfo() {

result.put("code_challenge_methods_supported", CODE_CHALLENGE_METHODS);

updateSupportedScopes();
result.put("scopes_supported", supportedScopes);

return result;
}

@Scheduled(fixedDelay = 5, timeUnit = TimeUnit.MINUTES)
@CacheEvict(allEntries = true, cacheNames = CACHE_KEY)
protected void evictCacheAndUpdateSupportedScopes() {
updateSupportedScopes();
LOG.debug("well-known config cache evicted");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package it.infn.mw.iam.test.oauth;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasItem;
Expand Down Expand Up @@ -46,6 +47,7 @@

import it.infn.mw.iam.IamLoginService;
import it.infn.mw.iam.core.web.wellknown.IamDiscoveryEndpoint;
import it.infn.mw.iam.config.CacheConfig;
import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest;


Expand All @@ -64,6 +66,10 @@ public class WellKnownConfigurationEndpointTests {
private static final String IAM_ORGANISATION_NAME_CLAIM = "organisation_name";
private static final String IAM_GROUPS_CLAIM = "groups";
private static final String IAM_EXTERNAL_AUTHN_CLAIM = "external_authn";

private static final String SYSTEM_SCOPE_0 = "new-scope0";
private static final String SYSTEM_SCOPE_1 = "new-scope1";


@Autowired
private MockMvc mvc;
Expand All @@ -73,7 +79,10 @@ public class WellKnownConfigurationEndpointTests {

@Autowired
private ObjectMapper mapper;


@Autowired
private CacheConfig cacheConfig;

@Test
public void testGrantTypesSupported() throws Exception {

Expand Down Expand Up @@ -152,5 +161,38 @@ public void testScopes() throws Exception {
assertTrue(returnedScopes.containsAll(unrestrictedScopes));

}

@Test
public void testWellKnownCacheEviction() throws Exception {

cacheConfig.evictWellKnownCache();

SystemScope scope = new SystemScope(SYSTEM_SCOPE_0);
scopeService.save(scope);

mvc.perform(get(endpoint))
.andExpect(status().isOk())
.andExpect(jsonPath("$.scopes_supported", notNullValue()))
.andExpect(jsonPath("$.scopes_supported").isArray())
.andExpect(jsonPath("$.scopes_supported", hasItem(SYSTEM_SCOPE_0)));

scope = new SystemScope(SYSTEM_SCOPE_1);
scopeService.save(scope);

mvc.perform(get(endpoint))
.andExpect(status().isOk())
.andExpect(jsonPath("$.scopes_supported", notNullValue()))
.andExpect(jsonPath("$.scopes_supported").isArray())
.andExpect(jsonPath("$.scopes_supported", not(SYSTEM_SCOPE_1)));

cacheConfig.evictWellKnownCache();

mvc.perform(get(endpoint))
.andExpect(status().isOk())
.andExpect(jsonPath("$.scopes_supported", notNullValue()))
.andExpect(jsonPath("$.scopes_supported").isArray())
.andExpect(jsonPath("$.scopes_supported", hasItem(SYSTEM_SCOPE_1)));

}

}