NIFI-11438 Set standard OpenID Connect Scopes

- Restored previous behavior of sending openid and email scopes for OpenID Connect token requests
- Added offline_access scope as the default value in nifi.properties to support Refresh Tokens

This closes #7168
Signed-off-by: Paul Grey <greyp@apache.org>
This commit is contained in:
exceptionfactory 2023-04-12 17:34:23 -05:00 committed by Paul Grey
parent 8586ac594e
commit 1639ecee11
No known key found for this signature in database
GPG Key ID: 8DDF32B9C7EE39D0
4 changed files with 23 additions and 5 deletions

View File

@ -579,7 +579,7 @@ OpenID Connect integration supports the following settings in _nifi.properties_.
by the OpenID Connect Provider according to the specification. If this value is `HS256`, `HS384`, or `HS512`, NiFi will attempt to validate HMAC protected tokens using the specified client secret.
If this value is `none`, NiFi will attempt to validate unsecured/plain tokens. Other values for this algorithm will attempt to parse as an RSA or EC algorithm to be used in conjunction with the
JSON Web Key (JWK) provided through the jwks_uri in the metadata found at the discovery URL
|`nifi.security.user.oidc.additional.scopes` | Comma separated scopes that are sent to OpenID Connect Provider in addition to `openid` and `email`
|`nifi.security.user.oidc.additional.scopes` | Comma separated scopes that are sent to OpenID Connect Provider in addition to `openid` and `email`. Authorization Servers require the `offline_access` scope to return a Refresh Token.
|`nifi.security.user.oidc.claim.identifying.user` | Claim that identifies the authenticated user. The default value is `email`. Claim names may need to be requested using the `nifi.security.user.oidc.additional.scopes` property
|`nifi.security.user.oidc.fallback.claims.identifying.user` | Comma-separated list of possible fallback claims used to identify the user when the `nifi.security.user.oidc.claim.identifying.user` claim is not found.
|`nifi.security.user.oidc.claim.groups` | Name of the ID token claim that contains an array of group names of which the

View File

@ -168,7 +168,8 @@
<nifi.security.user.oidc.client.id />
<nifi.security.user.oidc.client.secret />
<nifi.security.user.oidc.preferred.jwsalgorithm />
<nifi.security.user.oidc.additional.scopes />
<!-- Set additional scopes to support Refresh Token retrieval -->
<nifi.security.user.oidc.additional.scopes>offline_access</nifi.security.user.oidc.additional.scopes>
<nifi.security.user.oidc.claim.identifying.user />
<nifi.security.user.oidc.fallback.claims.identifying.user />
<nifi.security.user.oidc.claim.groups>groups</nifi.security.user.oidc.claim.groups>

View File

@ -21,7 +21,6 @@ import static com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod.CLIENT_SEC
import static com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod.NONE;
import com.nimbusds.oauth2.sdk.ParseException;
import com.nimbusds.oauth2.sdk.Scope;
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.web.security.oidc.OidcConfigurationException;
@ -30,8 +29,11 @@ import org.apache.nifi.web.security.oidc.client.web.OidcRegistrationProperty;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.web.client.RestOperations;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@ -46,6 +48,8 @@ public class StandardClientRegistrationProvider implements ClientRegistrationPro
private static final String REGISTRATION_REDIRECT_URI = String.format("{baseUrl}%s", OidcUrlPath.CALLBACK.getPath());
private static final Set<String> STANDARD_SCOPES = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(OidcScopes.OPENID, OidcScopes.EMAIL)));
private final NiFiProperties properties;
private final RestOperations restOperations;
@ -77,8 +81,7 @@ public class StandardClientRegistrationProvider implements ClientRegistrationPro
final String jwkSetUri = providerMetadata.getJWKSetURI().toASCIIString();
final String userInfoUri = providerMetadata.getUserInfoEndpointURI().toASCIIString();
final Scope metadataScope = providerMetadata.getScopes();
final Set<String> scope = new LinkedHashSet<>(metadataScope.toStringList());
final Set<String> scope = new LinkedHashSet<>(STANDARD_SCOPES);
final List<String> additionalScopes = properties.getOidcAdditionalScopes();
scope.addAll(additionalScopes);

View File

@ -28,12 +28,16 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.core.AuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.web.client.RestOperations;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@ -61,6 +65,8 @@ class StandardClientRegistrationProviderTest {
private static final String USER_NAME_ATTRIBUTE_NAME = "email";
private static final Set<String> EXPECTED_SCOPES = new LinkedHashSet<>(Arrays.asList(OidcScopes.OPENID, OidcScopes.EMAIL, OidcScopes.PROFILE));
private static final String INVALID_CONFIGURATION = "{}";
@Mock
@ -92,6 +98,9 @@ class StandardClientRegistrationProviderTest {
assertEquals(USER_INFO_URI.toString(), userInfoEndpoint.getUri());
assertEquals(USER_NAME_ATTRIBUTE_NAME, userInfoEndpoint.getUserNameAttributeName());
assertEquals(AuthenticationMethod.HEADER, userInfoEndpoint.getAuthenticationMethod());
final Set<String> scopes = clientRegistration.getScopes();
assertEquals(EXPECTED_SCOPES, scopes);
}
@Test
@ -120,6 +129,7 @@ class StandardClientRegistrationProviderTest {
properties.put(NiFiProperties.SECURITY_USER_OIDC_CLIENT_ID, CLIENT_ID);
properties.put(NiFiProperties.SECURITY_USER_OIDC_CLIENT_SECRET, CLIENT_SECRET);
properties.put(NiFiProperties.SECURITY_USER_OIDC_CLAIM_IDENTIFYING_USER, USER_NAME_ATTRIBUTE_NAME);
properties.put(NiFiProperties.SECURITY_USER_OIDC_ADDITIONAL_SCOPES, OidcScopes.PROFILE);
return NiFiProperties.createBasicNiFiProperties(null, properties);
}
@ -131,6 +141,10 @@ class StandardClientRegistrationProviderTest {
providerMetadata.setUserInfoEndpointURI(USER_INFO_URI);
providerMetadata.setAuthorizationEndpointURI(AUTHORIZATION_ENDPOINT_URI);
final Scope scopes = new Scope();
scopes.add(OidcScopes.OPENID);
scopes.add(OidcScopes.EMAIL);
scopes.add(OidcScopes.PROFILE);
scopes.add(OidcScopes.ADDRESS);
providerMetadata.setScopes(scopes);
return providerMetadata;
}