This is an automated email from the ASF dual-hosted git repository.

bbende pushed a commit to branch support/nifi-1.x
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/support/nifi-1.x by this push:
     new db919bc494 NIFI-12418 Corrected Provider Groups Missing in Refreshed 
Tokens (#8126)
db919bc494 is described below

commit db919bc49401262edfad3c5beb00b169433954ce
Author: David Handermann <exceptionfact...@apache.org>
AuthorDate: Mon Dec 18 10:53:23 2023 -0600

    NIFI-12418 Corrected Provider Groups Missing in Refreshed Tokens (#8126)
    
    - Updated OidcBearerTokenRefreshFilter to maintain current Identity 
Provider Groups when generating refreshed application Bearer Tokens
    - Refactored LoginAuthenticationToken to remove unnecessary optional 
constructors and use java.time.Instant for expiration
    - Added Issuer Provider with implementation for Bearer Token Issuer based 
on host and port properties
---
 .../org/apache/nifi/web/api/AccessResource.java    | 18 +++--
 .../JwtAuthenticationSecurityConfiguration.java    |  9 ++-
 .../SamlAuthenticationSecurityConfiguration.java   |  5 +-
 .../web/security/jwt/provider/IssuerProvider.java  | 31 +++++++++
 .../jwt/provider/StandardBearerTokenProvider.java  | 26 +++-----
 .../jwt/provider/StandardIssuerProvider.java       | 73 ++++++++++++++++++++
 .../client/web/OidcBearerTokenRefreshFilter.java   | 34 +++++++---
 .../OidcAuthenticationSuccessHandler.java          | 19 ++----
 .../Saml2AuthenticationSuccessHandler.java         | 11 ++-
 .../security/token/LoginAuthenticationToken.java   | 71 +++-----------------
 .../provider/StandardBearerTokenProviderTest.java  | 38 ++++++-----
 .../jwt/provider/StandardIssuerProviderTest.java   | 78 ++++++++++++++++++++++
 .../web/OidcBearerTokenRefreshFilterTest.java      | 41 +++++++++++-
 .../OidcAuthenticationSuccessHandlerTest.java      | 19 +-----
 .../Saml2AuthenticationSuccessHandlerTest.java     |  5 +-
 15 files changed, 321 insertions(+), 157 deletions(-)

diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
index 049e26eacc..16f2816905 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
@@ -34,17 +34,17 @@ import org.apache.nifi.authorization.user.NiFiUserDetails;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.authorization.util.IdentityMappingUtil;
 import org.apache.nifi.util.FormatUtils;
-import org.apache.nifi.web.api.dto.AccessTokenExpirationDTO;
-import org.apache.nifi.web.api.entity.AccessTokenExpirationEntity;
-import org.apache.nifi.web.security.cookie.ApplicationCookieName;
 import org.apache.nifi.web.api.dto.AccessConfigurationDTO;
 import org.apache.nifi.web.api.dto.AccessStatusDTO;
+import org.apache.nifi.web.api.dto.AccessTokenExpirationDTO;
 import org.apache.nifi.web.api.entity.AccessConfigurationEntity;
 import org.apache.nifi.web.api.entity.AccessStatusEntity;
+import org.apache.nifi.web.api.entity.AccessTokenExpirationEntity;
 import org.apache.nifi.web.security.InvalidAuthenticationException;
 import org.apache.nifi.web.security.LogoutException;
 import org.apache.nifi.web.security.ProxiedEntitiesUtils;
 import org.apache.nifi.web.security.UntrustedProxyException;
+import org.apache.nifi.web.security.cookie.ApplicationCookieName;
 import org.apache.nifi.web.security.jwt.provider.BearerTokenProvider;
 import org.apache.nifi.web.security.jwt.revocation.JwtLogoutListener;
 import org.apache.nifi.web.security.kerberos.KerberosService;
@@ -83,6 +83,7 @@ import javax.ws.rs.core.UriBuilder;
 import java.net.URI;
 import java.security.cert.X509Certificate;
 import java.time.Instant;
+import java.util.Collections;
 import java.util.Optional;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
@@ -352,11 +353,13 @@ public class AccessResource extends ApplicationResource {
                 }
 
                 final String expirationFromProperties = 
properties.getKerberosAuthenticationExpiration();
-                long expiration = 
Math.round(FormatUtils.getPreciseTimeDuration(expirationFromProperties, 
TimeUnit.MILLISECONDS));
+                final long expirationDuration = 
Math.round(FormatUtils.getPreciseTimeDuration(expirationFromProperties, 
TimeUnit.MILLISECONDS));
+                final Instant expiration = 
Instant.now().plusMillis(expirationDuration);
+
                 final String rawIdentity = authentication.getName();
                 final String mappedIdentity = 
IdentityMappingUtil.mapIdentity(rawIdentity, 
IdentityMappingUtil.getIdentityMappings(properties));
 
-                final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(mappedIdentity, expiration, "KerberosService");
+                final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(mappedIdentity, expiration, Collections.emptySet());
                 final String token = 
bearerTokenProvider.getBearerToken(loginAuthenticationToken);
                 final URI uri = URI.create(generateResourceUri("access", 
"kerberos"));
                 setBearerToken(httpServletResponse, token);
@@ -422,10 +425,11 @@ public class AccessResource extends ApplicationResource {
             final AuthenticationResponse authenticationResponse = 
loginIdentityProvider.authenticate(new LoginCredentials(username, password));
             final String rawIdentity = authenticationResponse.getIdentity();
             final String mappedIdentity = 
IdentityMappingUtil.mapIdentity(rawIdentity, 
IdentityMappingUtil.getIdentityMappings(properties));
-            final long expiration = authenticationResponse.getExpiration();
+            final long expirationDuration = 
authenticationResponse.getExpiration();
+            final Instant expiration = 
Instant.now().plusMillis(expirationDuration);
 
             // create the authentication token
-            loginAuthenticationToken = new 
LoginAuthenticationToken(mappedIdentity, expiration, 
authenticationResponse.getIssuer());
+            loginAuthenticationToken = new 
LoginAuthenticationToken(mappedIdentity, expiration, Collections.emptySet());
         } catch (final InvalidLoginCredentialsException ilce) {
             throw new IllegalArgumentException("The supplied username and 
password are not valid.", ilce);
         } catch (final IdentityAccessException iae) {
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/JwtAuthenticationSecurityConfiguration.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/JwtAuthenticationSecurityConfiguration.java
index 47a254a5bd..100e500cad 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/JwtAuthenticationSecurityConfiguration.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/JwtAuthenticationSecurityConfiguration.java
@@ -36,7 +36,9 @@ import 
org.apache.nifi.web.security.jwt.key.StandardVerificationKeySelector;
 import 
org.apache.nifi.web.security.jwt.key.service.StandardVerificationKeyService;
 import org.apache.nifi.web.security.jwt.key.service.VerificationKeyService;
 import org.apache.nifi.web.security.jwt.provider.BearerTokenProvider;
+import org.apache.nifi.web.security.jwt.provider.IssuerProvider;
 import org.apache.nifi.web.security.jwt.provider.StandardBearerTokenProvider;
+import org.apache.nifi.web.security.jwt.provider.StandardIssuerProvider;
 import org.apache.nifi.web.security.jwt.provider.SupportedClaim;
 import org.apache.nifi.web.security.jwt.resolver.StandardBearerTokenResolver;
 import org.apache.nifi.web.security.jwt.revocation.JwtLogoutListener;
@@ -181,7 +183,12 @@ public class JwtAuthenticationSecurityConfiguration {
 
     @Bean
     public BearerTokenProvider bearerTokenProvider() {
-        return new StandardBearerTokenProvider(jwsSignerProvider());
+        return new StandardBearerTokenProvider(jwsSignerProvider(), 
issuerProvider());
+    }
+
+    @Bean
+    public IssuerProvider issuerProvider() {
+        return new 
StandardIssuerProvider(niFiProperties.getProperty(NiFiProperties.WEB_HTTPS_HOST),
 niFiProperties.getConfiguredHttpOrHttpsPort());
     }
 
     @Bean
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/SamlAuthenticationSecurityConfiguration.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/SamlAuthenticationSecurityConfiguration.java
index 93070c8e58..2005dca4cb 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/SamlAuthenticationSecurityConfiguration.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/SamlAuthenticationSecurityConfiguration.java
@@ -368,14 +368,11 @@ public class SamlAuthenticationSecurityConfiguration {
     private Saml2AuthenticationSuccessHandler 
getAuthenticationSuccessHandler() {
         final long authenticationExpiration = (long) 
FormatUtils.getPreciseTimeDuration(properties.getSamlAuthenticationExpiration(),
 TimeUnit.MILLISECONDS);
         final Duration expiration = 
Duration.ofMillis(authenticationExpiration);
-        final String entityId = properties.getSamlServiceProviderEntityId();
-        final String issuer = entityId == null ? 
Saml2RegistrationProperty.REGISTRATION_ID.getProperty() : entityId;
         final Saml2AuthenticationSuccessHandler handler = new 
Saml2AuthenticationSuccessHandler(
                 bearerTokenProvider,
                 IdentityMappingUtil.getIdentityMappings(properties),
                 IdentityMappingUtil.getGroupMappings(properties),
-                expiration,
-                issuer
+                expiration
         );
 
         final String identityAttributeName = 
properties.getSamlIdentityAttributeName();
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/provider/IssuerProvider.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/provider/IssuerProvider.java
new file mode 100644
index 0000000000..83785de8f1
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/provider/IssuerProvider.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.web.security.jwt.provider;
+
+import java.net.URI;
+
+/**
+ * JSON Web Token Issuer Provider abstracts determination of local address for 
issuer claims
+ */
+public interface IssuerProvider {
+    /**
+     * Get Issuer URI for issuer claims
+     *
+     * @return Issuer URI
+     */
+    URI getIssuer();
+}
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/provider/StandardBearerTokenProvider.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/provider/StandardBearerTokenProvider.java
index 9ba3295faf..9e8d728067 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/provider/StandardBearerTokenProvider.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/provider/StandardBearerTokenProvider.java
@@ -30,9 +30,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.core.GrantedAuthority;
 
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
+import java.net.URI;
 import java.time.Duration;
 import java.time.Instant;
 import java.util.Collection;
@@ -48,16 +46,17 @@ import java.util.stream.Collectors;
 public class StandardBearerTokenProvider implements BearerTokenProvider {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(StandardBearerTokenProvider.class);
 
-    private static final String URL_ENCODED_CHARACTER_SET = 
StandardCharsets.UTF_8.name();
-
     private static final Duration MAXIMUM_EXPIRATION = Duration.ofHours(12);
 
     private static final Duration MINIMUM_EXPIRATION = Duration.ofMinutes(1);
 
     private final JwsSignerProvider jwsSignerProvider;
 
-    public StandardBearerTokenProvider(final JwsSignerProvider 
jwsSignerProvider) {
+    private final IssuerProvider issuerProvider;
+
+    public StandardBearerTokenProvider(final JwsSignerProvider 
jwsSignerProvider, final IssuerProvider issuerProvider) {
         this.jwsSignerProvider = jwsSignerProvider;
+        this.issuerProvider = issuerProvider;
     }
 
     /**
@@ -73,7 +72,10 @@ public class StandardBearerTokenProvider implements 
BearerTokenProvider {
         final String username = loginAuthenticationToken.getName();
 
         final List<String> groups = 
getGroups(loginAuthenticationToken.getAuthorities());
-        final String issuer = 
getUrlEncoded(loginAuthenticationToken.getIssuer());
+
+        final URI issuerUri = issuerProvider.getIssuer();
+        final String issuer = issuerUri.toString();
+
         final Date now = new Date();
         final Date expirationTime = 
getExpirationTime(loginAuthenticationToken);
         final JWTClaimsSet claims = new JWTClaimsSet.Builder()
@@ -91,7 +93,7 @@ public class StandardBearerTokenProvider implements 
BearerTokenProvider {
     }
 
     private Date getExpirationTime(final LoginAuthenticationToken 
loginAuthenticationToken) {
-        Instant expiration = 
Instant.ofEpochMilli(loginAuthenticationToken.getExpiration());
+        Instant expiration = loginAuthenticationToken.getExpiration();
 
         final Instant maximumExpiration = 
Instant.now().plus(MAXIMUM_EXPIRATION);
         final Instant minimumExpiration = 
Instant.now().plus(MINIMUM_EXPIRATION);
@@ -130,14 +132,6 @@ public class StandardBearerTokenProvider implements 
BearerTokenProvider {
         return jwsObject.serialize();
     }
 
-    private String getUrlEncoded(final String string) {
-        try {
-            return URLEncoder.encode(string, URL_ENCODED_CHARACTER_SET);
-        } catch (final UnsupportedEncodingException e) {
-            throw new IllegalArgumentException(String.format("URL Encoding 
[%s] Failed", string), e);
-        }
-    }
-
     private List<String> getGroups(final Collection<? extends 
GrantedAuthority> authorities) {
         return 
authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
     }
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/provider/StandardIssuerProvider.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/provider/StandardIssuerProvider.java
new file mode 100644
index 0000000000..f45bbffa37
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/provider/StandardIssuerProvider.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.web.security.jwt.provider;
+
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+
+/**
+ * Standard Issuer Provider with configurable host and port for HTTPS URI 
construction
+ */
+public class StandardIssuerProvider implements IssuerProvider {
+    private static final String URI_FORMAT = "https://%s:%d";;
+
+    private final URI issuer;
+
+    /**
+     * Standard Issuer Provider constructor with optional host and required 
port properties
+     *
+     * @param host HTTPS Host address can be null or empty to default to 
InetAddress.getLocalHost() resolution
+     * @param port HTTPS port number
+     */
+    public StandardIssuerProvider(final String host, final int port) {
+        final String resolvedHost = getResolvedHost(host);
+        final String uri = String.format(URI_FORMAT, resolvedHost, port);
+        this.issuer = URI.create(uri);
+    }
+
+    /**
+     * Get Issuer URI for issuer claims
+     *
+     * @return Issuer URI
+     */
+    @Override
+    public URI getIssuer() {
+        return issuer;
+    }
+
+    private String getResolvedHost(final String host) {
+        final String resolvedHost;
+
+        if (host == null || host.isEmpty()) {
+            resolvedHost = getLocalHost();
+        } else {
+            resolvedHost = host;
+        }
+
+        return resolvedHost;
+    }
+
+    private String getLocalHost() {
+        try {
+            final InetAddress localHostAddress = InetAddress.getLocalHost();
+            return localHostAddress.getCanonicalHostName();
+        } catch (final UnknownHostException e) {
+            throw new IllegalStateException("Failed to resolve local host 
address", e);
+        }
+    }
+}
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/client/web/OidcBearerTokenRefreshFilter.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/client/web/OidcBearerTokenRefreshFilter.java
index e8f322d0d0..b9cb7c5d56 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/client/web/OidcBearerTokenRefreshFilter.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/client/web/OidcBearerTokenRefreshFilter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.web.security.oidc.client.web;
 
+import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.web.security.cookie.ApplicationCookieName;
 import org.apache.nifi.web.security.cookie.ApplicationCookieService;
@@ -27,6 +28,8 @@ import org.apache.nifi.web.util.RequestUriBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextHolder;
 import 
org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
@@ -56,8 +59,10 @@ import java.time.Duration;
 import java.time.Instant;
 import java.util.Collections;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.stream.Collectors;
 
 /**
  * OpenID Connect Filter for evaluating the application Bearer Token and 
returning an updated Bearer Token after successful OAuth2 Refresh Token 
processing
@@ -143,8 +148,7 @@ public class OidcBearerTokenRefreshFilter extends 
OncePerRequestFilter {
                     logger.warn("Identity [{}] OpenID Connect Refresh Token 
not found", userIdentity);
                 } else {
                     final URI resourceUri = 
RequestUriBuilder.fromHttpServletRequest(request).path(ROOT_PATH).build();
-                    final String issuer = resourceUri.toString();
-                    final String bearerToken = getBearerToken(userIdentity, 
issuer, tokenResponse);
+                    final String bearerToken = getBearerToken(userIdentity, 
tokenResponse);
                     applicationCookieService.addSessionCookie(resourceUri, 
response, ApplicationCookieName.AUTHORIZATION_BEARER, bearerToken);
                 }
             }
@@ -174,20 +178,20 @@ public class OidcBearerTokenRefreshFilter extends 
OncePerRequestFilter {
         return 
authorizedClientRepository.loadAuthorizedClient(OidcRegistrationProperty.REGISTRATION_ID.getProperty(),
 principal, request);
     }
 
-    private String getBearerToken(final String userIdentity, final String 
issuer, final OAuth2AccessTokenResponse tokenResponse) {
+    private String getBearerToken(final String userIdentity, final 
OAuth2AccessTokenResponse tokenResponse) {
         final OAuth2AccessToken accessToken = tokenResponse.getAccessToken();
-        final long sessionExpiration = getSessionExpiration(accessToken);
-        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(userIdentity, userIdentity, sessionExpiration, issuer);
+        final Instant sessionExpiration = getSessionExpiration(accessToken);
+        final Set<? extends GrantedAuthority> providerAuthorities = 
getProviderAuthorities();
+        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(userIdentity, sessionExpiration, providerAuthorities);
         return bearerTokenProvider.getBearerToken(loginAuthenticationToken);
     }
 
-    private long getSessionExpiration(final OAuth2AccessToken accessToken) {
+    private Instant getSessionExpiration(final OAuth2AccessToken accessToken) {
         final Instant tokenExpiration = accessToken.getExpiresAt();
         if (tokenExpiration == null) {
             throw new IllegalArgumentException("OpenID Connect Access Token 
expiration claim not found");
         }
-        final Duration expiration = Duration.between(Instant.now(), 
tokenExpiration);
-        return expiration.toMillis();
+        return tokenExpiration;
     }
 
     private OAuth2AccessTokenResponse getRefreshTokenResponse(final 
OidcAuthorizedClient authorizedClient, final HttpServletRequest request, final 
HttpServletResponse response) {
@@ -229,4 +233,18 @@ public class OidcBearerTokenRefreshFilter extends 
OncePerRequestFilter {
         final OidcUser oidcUser = new DefaultOidcUser(Collections.emptyList(), 
idToken, SupportedClaim.SUBJECT.getClaim());
         return new OAuth2AuthenticationToken(oidcUser, 
Collections.emptyList(), clientRegistration.getRegistrationId());
     }
+
+    private Set<? extends GrantedAuthority> getProviderAuthorities() {
+        final Set<? extends GrantedAuthority> authorities;
+
+        final NiFiUser user = NiFiUserUtils.getNiFiUser();
+        final Set<String> providerGroups = user.getIdentityProviderGroups();
+        if (providerGroups == null) {
+            authorities = Collections.emptySet();
+        } else {
+            authorities = 
providerGroups.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
+        }
+
+        return authorities;
+    }
 }
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/web/authentication/OidcAuthenticationSuccessHandler.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/web/authentication/OidcAuthenticationSuccessHandler.java
index 8dbbc1c24b..27fcde484b 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/web/authentication/OidcAuthenticationSuccessHandler.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/web/authentication/OidcAuthenticationSuccessHandler.java
@@ -38,7 +38,6 @@ import 
org.springframework.security.web.authentication.SimpleUrlAuthenticationSu
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.net.URI;
-import java.time.Duration;
 import java.time.Instant;
 import java.util.Collections;
 import java.util.List;
@@ -114,29 +113,23 @@ public class OidcAuthenticationSuccessHandler extends 
SimpleUrlAuthenticationSuc
         final Set<String> groups = getGroups(oidcUser);
 
         final OAuth2AccessToken accessToken = 
getAccessToken(authenticationToken);
-        final String bearerToken = getBearerToken(identity, oidcUser, 
accessToken, groups);
+        final String bearerToken = getBearerToken(identity, accessToken, 
groups);
         applicationCookieService.addSessionCookie(resourceUri, response, 
ApplicationCookieName.AUTHORIZATION_BEARER, bearerToken);
     }
 
-    private String getBearerToken(final String identity, final OidcUser 
oidcUser, final OAuth2AccessToken accessToken, final Set<String> groups) {
-        final long sessionExpiration = getSessionExpiration(accessToken);
-        final String issuer = oidcUser.getIssuer().toString();
+    private String getBearerToken(final String identity, final 
OAuth2AccessToken accessToken, final Set<String> groups) {
+        final Instant sessionExpiration = getSessionExpiration(accessToken);
         final Set<? extends GrantedAuthority> authorities = 
groups.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
-        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(identity, identity, sessionExpiration, issuer, 
authorities);
+        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(identity, sessionExpiration, authorities);
         return bearerTokenProvider.getBearerToken(loginAuthenticationToken);
     }
 
-    private long getSessionExpiration(final OAuth2Token token) {
+    private Instant getSessionExpiration(final OAuth2Token token) {
         final Instant tokenExpiration = token.getExpiresAt();
         if (tokenExpiration == null) {
             throw new IllegalArgumentException("Token expiration claim not 
found");
         }
-        final Instant tokenIssued = token.getIssuedAt();
-        if (tokenIssued == null) {
-            throw new IllegalArgumentException("Token issued claim not found");
-        }
-        final Duration expiration = Duration.between(tokenIssued, 
tokenExpiration);
-        return expiration.toMillis();
+        return tokenExpiration;
     }
 
     private OAuth2AuthenticationToken getAuthenticationToken(final 
Authentication authentication) {
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/saml2/web/authentication/Saml2AuthenticationSuccessHandler.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/saml2/web/authentication/Saml2AuthenticationSuccessHandler.java
index 866d0928d4..b3376b3226 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/saml2/web/authentication/Saml2AuthenticationSuccessHandler.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/saml2/web/authentication/Saml2AuthenticationSuccessHandler.java
@@ -35,6 +35,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.net.URI;
 import java.time.Duration;
+import java.time.Instant;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -58,8 +59,6 @@ public class Saml2AuthenticationSuccessHandler extends 
SimpleUrlAuthenticationSu
 
     private final Duration expiration;
 
-    private final String issuer;
-
     private Converter<Saml2AuthenticatedPrincipal, String> identityConverter = 
Saml2AuthenticatedPrincipal::getName;
 
     /**
@@ -69,20 +68,17 @@ public class Saml2AuthenticationSuccessHandler extends 
SimpleUrlAuthenticationSu
      * @param userIdentityMappings User Identity Mappings
      * @param groupIdentityMappings Group Identity Mappings
      * @param expiration Expiration for generated tokens
-     * @param issuer Token Issuer
      */
     public Saml2AuthenticationSuccessHandler(
             final BearerTokenProvider bearerTokenProvider,
             final List<IdentityMapping> userIdentityMappings,
             final List<IdentityMapping> groupIdentityMappings,
-            final Duration expiration,
-            final String issuer
+            final Duration expiration
     ) {
         this.bearerTokenProvider = Objects.requireNonNull(bearerTokenProvider, 
"Bearer Token Provider required");
         this.userIdentityMappings = 
Objects.requireNonNull(userIdentityMappings, "User Identity Mappings required");
         this.groupIdentityMappings = 
Objects.requireNonNull(groupIdentityMappings, "Group Identity Mappings 
required");
         this.expiration = Objects.requireNonNull(expiration, "Expiration 
required");
-        this.issuer = Objects.requireNonNull(issuer, "Issuer required");
     }
 
     /**
@@ -121,7 +117,8 @@ public class Saml2AuthenticationSuccessHandler extends 
SimpleUrlAuthenticationSu
 
     private String getBearerToken(final String identity, final Set<String> 
groups) {
         final Set<? extends GrantedAuthority> authorities = 
groups.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
-        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(identity, identity, expiration.toMillis(), issuer, 
authorities);
+        final Instant sessionExpiration = Instant.now().plus(expiration);
+        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(identity, sessionExpiration, authorities);
         return bearerTokenProvider.getBearerToken(loginAuthenticationToken);
     }
 
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/token/LoginAuthenticationToken.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/token/LoginAuthenticationToken.java
index ad345c8404..d0496fc18e 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/token/LoginAuthenticationToken.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/token/LoginAuthenticationToken.java
@@ -21,56 +21,29 @@ import org.springframework.security.core.GrantedAuthority;
 
 import java.time.Instant;
 import java.util.Collection;
+import java.util.Objects;
 
 /**
- * This is an Authentication Token for logging in. Once a user is 
authenticated, they can be issued an ID token.
+ * Login Authentication Token containing mapped Identity and Expiration Time 
to exchange for Application Bearer Token
  */
 public class LoginAuthenticationToken extends AbstractAuthenticationToken {
 
     private final String identity;
-    private final String username;
-    private final long expiration;
-    private final String issuer;
 
-    /**
-     * Creates a representation of the authentication token for a user.
-     *
-     * @param identity   The unique identifier for this user
-     * @param expiration The relative time to expiration in milliseconds
-     * @param issuer     The IdentityProvider implementation that generated 
this token
-     */
-    public LoginAuthenticationToken(final String identity, final long 
expiration, final String issuer) {
-        this(identity, null, expiration, issuer, null);
-    }
-
-    /**
-     * Creates a representation of the authentication token for a user.
-     *
-     * @param identity    The unique identifier for this user (cannot be null 
or empty)
-     * @param username    The preferred username for this user
-     * @param expiration  The relative time to expiration in milliseconds
-     * @param issuer      The IdentityProvider implementation that generated 
this token
-     */
-    public LoginAuthenticationToken(final String identity, final String 
username, final long expiration, final String issuer) {
-        this(identity, username, expiration, issuer, null);
-    }
+    private final Instant expiration;
 
     /**
      * Creates a representation of the authentication token for a user.
      *
      * @param identity    The unique identifier for this user (cannot be null 
or empty)
-     * @param username    The preferred username for this user
-     * @param expiration  The relative time to expiration in milliseconds
-     * @param issuer      The IdentityProvider implementation that generated 
this token
+     * @param expiration  Instant at which the authenticated token is no 
longer valid
      * @param authorities The authorities that have been granted this token.
      */
-    public LoginAuthenticationToken(final String identity, final String 
username, final long expiration, final String issuer, Collection<? extends 
GrantedAuthority> authorities) {
+    public LoginAuthenticationToken(final String identity, final Instant 
expiration, Collection<? extends GrantedAuthority> authorities) {
         super(authorities);
         setAuthenticated(true);
         this.identity = identity;
-        this.username = username == null ? identity : username;
-        this.issuer = issuer;
-        this.expiration = Instant.now().plusMillis(expiration).toEpochMilli();
+        this.expiration = Objects.requireNonNull(expiration);
     }
 
     @Override
@@ -83,43 +56,17 @@ public class LoginAuthenticationToken extends 
AbstractAuthenticationToken {
         return identity;
     }
 
-    /**
-     * Returns the expiration instant in milliseconds. This value is an 
absolute point in time (i.e. Nov
-     * 16, 2015 11:30:00.000 GMT), not a relative time (i.e. 60 minutes). It 
is calculated by adding the
-     * relative expiration from the constructor to the timestamp at object 
creation.
-     *
-     * @return the expiration in millis
-     */
-    public long getExpiration() {
+    public Instant getExpiration() {
         return expiration;
     }
 
-    public String getIssuer() {
-        return issuer;
-    }
-
     @Override
     public String getName() {
-        return username;
+        return identity;
     }
 
     @Override
     public String toString() {
-        final Instant expirationTime = Instant.ofEpochMilli(expiration);
-        long remainingTime = expirationTime.toEpochMilli() - 
Instant.now().toEpochMilli();
-
-        return new StringBuilder("LoginAuthenticationToken for ")
-                .append(getName())
-                .append(" issued by ")
-                .append(getIssuer())
-                .append(" expiring at ")
-                .append(expirationTime)
-                .append(" [")
-                .append(getExpiration())
-                .append(" ms, ")
-                .append(remainingTime)
-                .append(" ms remaining]")
-                .toString();
+        return getName();
     }
-
 }
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/provider/StandardBearerTokenProviderTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/provider/StandardBearerTokenProviderTest.java
index 2e105d3d34..1cce46dce4 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/provider/StandardBearerTokenProviderTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/provider/StandardBearerTokenProviderTest.java
@@ -36,6 +36,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 
+import java.net.URI;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.NoSuchAlgorithmException;
@@ -59,17 +60,15 @@ import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
 public class StandardBearerTokenProviderTest {
-    private static final String USERNAME = "USERNAME";
-
     private static final String IDENTITY = "IDENTITY";
 
-    private static final Duration EXPIRATION = Duration.ofHours(1);
+    private static final Instant EXPIRATION = Instant.now().plusSeconds(300);
 
     private static final Duration MAXIMUM_DURATION_EXCEEDED = 
Duration.parse("PT12H5M");
 
     private static final Duration MINIMUM_DURATION_EXCEEDED = 
Duration.parse("PT30S");
 
-    private static final String ISSUER = "ISSUER";
+    private static final URI ISSUER = URI.create("https://localhost:8443";);
 
     private static final String KEY_ALGORITHM = "RSA";
 
@@ -84,6 +83,9 @@ public class StandardBearerTokenProviderTest {
     @Mock
     private JwsSignerProvider jwsSignerProvider;
 
+    @Mock
+    private IssuerProvider issuerProvider;
+
     private StandardBearerTokenProvider provider;
 
     private JWSVerifier jwsVerifier;
@@ -97,7 +99,7 @@ public class StandardBearerTokenProviderTest {
 
     @BeforeEach
     public void setProvider() {
-        provider = new StandardBearerTokenProvider(jwsSignerProvider);
+        provider = new StandardBearerTokenProvider(jwsSignerProvider, 
issuerProvider);
 
         jwsVerifier = new RSASSAVerifier((RSAPublicKey) keyPair.getPublic());
         final JWSSigner jwsSigner = new RSASSASigner(keyPair.getPrivate());
@@ -105,11 +107,13 @@ public class StandardBearerTokenProviderTest {
         final String keyIdentifier = UUID.randomUUID().toString();
         final JwsSignerContainer jwsSignerContainer = new 
JwsSignerContainer(keyIdentifier, JWS_ALGORITHM, jwsSigner);
         
when(jwsSignerProvider.getJwsSignerContainer(isA(Instant.class))).thenReturn(jwsSignerContainer);
+
+        when(issuerProvider.getIssuer()).thenReturn(ISSUER);
     }
 
     @Test
     public void testGetBearerToken() throws ParseException, JOSEException {
-        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(IDENTITY, USERNAME, EXPIRATION.toMillis(), ISSUER);
+        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(IDENTITY, EXPIRATION, Collections.emptySet());
 
         final String bearerToken = 
provider.getBearerToken(loginAuthenticationToken);
 
@@ -121,7 +125,7 @@ public class StandardBearerTokenProviderTest {
         final GrantedAuthority grantedAuthority = new 
SimpleGrantedAuthority(GROUP);
         final Collection<GrantedAuthority> authorities = 
Collections.singletonList(grantedAuthority);
 
-        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(IDENTITY, USERNAME, EXPIRATION.toMillis(), ISSUER, 
authorities);
+        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(IDENTITY, EXPIRATION, authorities);
 
         final String bearerToken = 
provider.getBearerToken(loginAuthenticationToken);
 
@@ -130,8 +134,8 @@ public class StandardBearerTokenProviderTest {
 
     @Test
     public void testGetBearerTokenExpirationMaximum() throws ParseException, 
JOSEException {
-        final long expiration = MAXIMUM_DURATION_EXCEEDED.toMillis();
-        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(IDENTITY, USERNAME, expiration, ISSUER);
+        final Instant expiration = 
Instant.now().plus(MAXIMUM_DURATION_EXCEEDED);
+        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(IDENTITY, expiration, Collections.emptySet());
 
         final String bearerToken = 
provider.getBearerToken(loginAuthenticationToken);
 
@@ -140,7 +144,7 @@ public class StandardBearerTokenProviderTest {
         final Date claimExpirationTime = claims.getExpirationTime();
         assertNotNull(claimExpirationTime, "Expiration Time not found");
 
-        final Date loginExpirationTime = new 
Date(loginAuthenticationToken.getExpiration());
+        final Date loginExpirationTime = 
Date.from(loginAuthenticationToken.getExpiration());
         assertNotSame(loginExpirationTime.toString(), 
claimExpirationTime.toString(), "Expiration Time matched");
 
         
assertTrue(claimExpirationTime.toInstant().isBefore(loginExpirationTime.toInstant()),
 "Claim Expiration after Login Expiration");
@@ -148,8 +152,8 @@ public class StandardBearerTokenProviderTest {
 
     @Test
     public void testGetBearerTokenExpirationMinimum() throws ParseException, 
JOSEException {
-        final long expiration = MINIMUM_DURATION_EXCEEDED.toMillis();
-        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(IDENTITY, USERNAME, expiration, ISSUER);
+        final Instant expiration = 
Instant.now().plus(MINIMUM_DURATION_EXCEEDED);
+        final LoginAuthenticationToken loginAuthenticationToken = new 
LoginAuthenticationToken(IDENTITY, expiration, Collections.emptySet());
 
         final String bearerToken = 
provider.getBearerToken(loginAuthenticationToken);
 
@@ -158,7 +162,7 @@ public class StandardBearerTokenProviderTest {
         final Date claimExpirationTime = claims.getExpirationTime();
         assertNotNull(claimExpirationTime, "Expiration Time not found");
 
-        final Date loginExpirationTime = new 
Date(loginAuthenticationToken.getExpiration());
+        final Date loginExpirationTime = 
Date.from(loginAuthenticationToken.getExpiration());
         assertNotSame(loginExpirationTime.toString(), 
claimExpirationTime.toString(), "Expiration Time matched");
 
         
assertTrue(claimExpirationTime.toInstant().isAfter(loginExpirationTime.toInstant()),
 "Claim Expiration before Login Expiration");
@@ -179,13 +183,13 @@ public class StandardBearerTokenProviderTest {
         final Date claimExpirationTime = claims.getExpirationTime();
         assertNotNull(claimExpirationTime, "Expiration Time not found");
 
-        final Date loginExpirationTime = new 
Date(loginAuthenticationToken.getExpiration());
+        final Date loginExpirationTime = 
Date.from(loginAuthenticationToken.getExpiration());
         assertEquals(loginExpirationTime.toString(), 
claimExpirationTime.toString(), "Expiration Time not matched");
 
-        assertEquals(ISSUER, claims.getIssuer());
-        assertEquals(Collections.singletonList(ISSUER), claims.getAudience());
+        assertEquals(ISSUER.toString(), claims.getIssuer());
+        assertEquals(Collections.singletonList(ISSUER.toString()), 
claims.getAudience());
         assertEquals(IDENTITY, claims.getSubject());
-        assertEquals(USERNAME, 
claims.getClaim(SupportedClaim.PREFERRED_USERNAME.getClaim()));
+        assertEquals(IDENTITY, 
claims.getClaim(SupportedClaim.PREFERRED_USERNAME.getClaim()));
         assertNotNull(claims.getJWTID(), "JSON Web Token Identifier not 
found");
 
         final List<String> groups = 
claims.getStringListClaim(SupportedClaim.GROUPS.getClaim());
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/provider/StandardIssuerProviderTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/provider/StandardIssuerProviderTest.java
new file mode 100644
index 0000000000..95438ffddf
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/jwt/provider/StandardIssuerProviderTest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.web.security.jwt.provider;
+
+import org.junit.jupiter.api.Test;
+
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assumptions.assumeFalse;
+
+class StandardIssuerProviderTest {
+    private static final String HTTPS_SCHEME = "https";
+
+    private static final String LOCALHOST = "localhost.localdomain";
+
+    private static final int PORT = 8443;
+
+    private static final String EMPTY = "";
+
+    @Test
+    void testGetIssuer() {
+        final StandardIssuerProvider provider = new 
StandardIssuerProvider(LOCALHOST, PORT);
+
+        final URI issuer = provider.getIssuer();
+
+        assertNotNull(issuer);
+        assertEquals(HTTPS_SCHEME, issuer.getScheme());
+        assertEquals(LOCALHOST, issuer.getHost());
+        assertEquals(PORT, issuer.getPort());
+        assertEquals(EMPTY, issuer.getPath());
+        assertNull(issuer.getQuery());
+    }
+
+    @Test
+    void testGetIssuerNullHostResolved() {
+        final String localHost = getLocalHost();
+        assumeFalse(localHost == null);
+
+        final StandardIssuerProvider provider = new 
StandardIssuerProvider(null, PORT);
+
+        final URI issuer = provider.getIssuer();
+
+        assertNotNull(issuer);
+        assertEquals(HTTPS_SCHEME, issuer.getScheme());
+        assertEquals(localHost, issuer.getHost());
+        assertEquals(PORT, issuer.getPort());
+        assertEquals(EMPTY, issuer.getPath());
+        assertNull(issuer.getQuery());
+    }
+
+    private String getLocalHost() {
+        try {
+            final InetAddress localHostAddress = InetAddress.getLocalHost();
+            return localHostAddress.getCanonicalHostName();
+        } catch (final UnknownHostException e) {
+            return null;
+        }
+    }
+}
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/client/web/OidcBearerTokenRefreshFilterTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/client/web/OidcBearerTokenRefreshFilterTest.java
index a3d2465168..a01c7ca375 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/client/web/OidcBearerTokenRefreshFilterTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/client/web/OidcBearerTokenRefreshFilterTest.java
@@ -16,16 +16,28 @@
  */
 package org.apache.nifi.web.security.oidc.client.web;
 
+import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserDetails;
+import org.apache.nifi.authorization.user.StandardNiFiUser;
 import org.apache.nifi.web.security.cookie.ApplicationCookieName;
 import org.apache.nifi.web.security.jwt.provider.BearerTokenProvider;
+import org.apache.nifi.web.security.token.LoginAuthenticationToken;
+import org.apache.nifi.web.security.token.NiFiAuthenticationToken;
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.springframework.mock.web.MockFilterChain;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.context.SecurityContextImpl;
 import 
org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
 import 
org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
 import 
org.springframework.security.oauth2.client.registration.ClientRegistration;
@@ -45,11 +57,14 @@ import java.io.IOException;
 import java.time.Duration;
 import java.time.Instant;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
@@ -89,6 +104,10 @@ class OidcBearerTokenRefreshFilterTest {
 
     private static final int INSTANT_OFFSET = 1;
 
+    private static final String PROVIDER_GROUP = "Authorized";
+
+    private static final Set<String> PROVIDER_GROUPS = 
Collections.singleton(PROVIDER_GROUP);
+
     @Mock
     BearerTokenProvider bearerTokenProvider;
 
@@ -107,6 +126,9 @@ class OidcBearerTokenRefreshFilterTest {
     @Mock
     OidcAuthorizedClient authorizedClient;
 
+    @Captor
+    ArgumentCaptor<LoginAuthenticationToken> tokenArgumentCaptor;
+
     MockHttpServletRequest request;
 
     MockHttpServletResponse response;
@@ -130,6 +152,11 @@ class OidcBearerTokenRefreshFilterTest {
         filterChain = new MockFilterChain();
     }
 
+    @AfterEach
+    void clearContext() {
+        SecurityContextHolder.clearContext();
+    }
+
     @Test
     void testDoFilterPathNotMatched() throws ServletException, IOException {
         filter.doFilter(request, response, filterChain);
@@ -193,6 +220,12 @@ class OidcBearerTokenRefreshFilterTest {
 
     @Test
     void testDoFilterBearerTokenTokenRefreshed() throws ServletException, 
IOException {
+        final NiFiUser user = new 
StandardNiFiUser.Builder().identity(IDENTITY).identityProviderGroups(PROVIDER_GROUPS).build();
+        final NiFiUserDetails userDetails = new NiFiUserDetails(user);
+        final NiFiAuthenticationToken authenticationToken = new 
NiFiAuthenticationToken(userDetails);
+        final SecurityContext securityContext = new 
SecurityContextImpl(authenticationToken);
+        SecurityContextHolder.setContext(securityContext);
+
         request.setServletPath(CURRENT_USER_URI);
 
         
when(bearerTokenResolver.resolve(eq(request))).thenReturn(BEARER_TOKEN);
@@ -220,13 +253,19 @@ class OidcBearerTokenRefreshFilterTest {
                 .build();
         
when(refreshTokenResponseClient.getTokenResponse(any())).thenReturn(tokenResponse);
 
-        
when(bearerTokenProvider.getBearerToken(any())).thenReturn(BEARER_TOKEN_REFRESHED);
+        
when(bearerTokenProvider.getBearerToken(tokenArgumentCaptor.capture())).thenReturn(BEARER_TOKEN_REFRESHED);
 
         filter.doFilter(request, response, filterChain);
 
         final Cookie cookie = 
response.getCookie(ApplicationCookieName.AUTHORIZATION_BEARER.getCookieName());
         assertNotNull(cookie);
         assertEquals(BEARER_TOKEN_REFRESHED, cookie.getValue());
+
+        final LoginAuthenticationToken loginAuthenticationToken = 
tokenArgumentCaptor.getValue();
+        final Iterator<GrantedAuthority> authorities = 
loginAuthenticationToken.getAuthorities().iterator();
+        assertTrue(authorities.hasNext());
+        final GrantedAuthority authority = authorities.next();
+        assertEquals(PROVIDER_GROUP, authority.getAuthority());
     }
 
     private Jwt getJwt(final Instant expiration) {
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/web/authentication/OidcAuthenticationSuccessHandlerTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/web/authentication/OidcAuthenticationSuccessHandlerTest.java
index 907c41c466..f0160b2b0b 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/web/authentication/OidcAuthenticationSuccessHandlerTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/oidc/web/authentication/OidcAuthenticationSuccessHandlerTest.java
@@ -40,9 +40,6 @@ import 
org.springframework.security.oauth2.core.oidc.user.OidcUser;
 
 import javax.servlet.ServletContext;
 import javax.servlet.http.Cookie;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URL;
 import java.time.Duration;
 import java.time.Instant;
 import java.time.temporal.ChronoUnit;
@@ -82,8 +79,6 @@ class OidcAuthenticationSuccessHandlerTest {
 
     private static final int SERVER_PORT = 8080;
 
-    private static final String ISSUER = "http://localhost/issuer";;
-
     private static final String LOCALHOST_URL = "http://localhost:8080";;
 
     private static final String TARGET_URL = String.format("%s%s", 
LOCALHOST_URL, UI_PATH);
@@ -183,18 +178,16 @@ class OidcAuthenticationSuccessHandlerTest {
         
verify(bearerTokenProvider).getBearerToken(authenticationTokenCaptor.capture());
 
         final LoginAuthenticationToken authenticationToken = 
authenticationTokenCaptor.getValue();
-        final Instant expiration = 
Instant.ofEpochMilli(authenticationToken.getExpiration());
+        final Instant expiration = authenticationToken.getExpiration();
 
         final ChronoUnit truncation = ChronoUnit.MINUTES;
         final Instant expirationTruncated = expiration.truncatedTo(truncation);
-        final Instant expected = 
Instant.now().plus(TOKEN_EXPIRATION).truncatedTo(truncation);
-        assertEquals(expected, expirationTruncated);
+        assertEquals(ACCESS_TOKEN_EXPIRES, expirationTruncated);
     }
 
     void setOidcUser() {
         
when(oidcUser.getClaimAsString(eq(USER_NAME_CLAIM))).thenReturn(IDENTITY);
         
when(oidcUser.getClaimAsStringList(eq(GROUPS_CLAIM))).thenReturn(Collections.singletonList(AUTHORITY));
-        when(oidcUser.getIssuer()).thenReturn(getIssuer());
     }
 
     StandardOAuth2AuthenticationToken getAuthenticationToken() {
@@ -202,12 +195,4 @@ class OidcAuthenticationSuccessHandlerTest {
         final Collection<? extends GrantedAuthority> authorities = 
Collections.singletonList(new SimpleGrantedAuthority(AUTHORITY));
         return new StandardOAuth2AuthenticationToken(oidcUser, authorities, 
OidcRegistrationProperty.REGISTRATION_ID.getProperty(), accessToken);
     }
-
-    URL getIssuer() {
-        try {
-            return URI.create(ISSUER).toURL();
-        } catch (IllegalArgumentException | MalformedURLException e) {
-            throw new RuntimeException(e);
-        }
-    }
 }
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/saml2/web/authentication/Saml2AuthenticationSuccessHandlerTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/saml2/web/authentication/Saml2AuthenticationSuccessHandlerTest.java
index 17e7abb793..8bc197fd9f 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/saml2/web/authentication/Saml2AuthenticationSuccessHandlerTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/saml2/web/authentication/Saml2AuthenticationSuccessHandlerTest.java
@@ -42,8 +42,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 @ExtendWith(MockitoExtension.class)
 class Saml2AuthenticationSuccessHandlerTest {
-    private static final String ISSUER = 
Saml2AuthenticationSuccessHandlerTest.class.getSimpleName();
-
     private static final Duration EXPIRATION = Duration.ofMinutes(1);
 
     private static final String IDENTITY = 
Authentication.class.getSimpleName();
@@ -103,8 +101,7 @@ class Saml2AuthenticationSuccessHandlerTest {
                 bearerTokenProvider,
                 Collections.singletonList(UPPER_IDENTITY_MAPPING),
                 Collections.singletonList(LOWER_IDENTITY_MAPPING),
-                EXPIRATION,
-                ISSUER
+                EXPIRATION
         );
         httpServletRequest = new MockHttpServletRequest();
         httpServletRequest.setServerPort(SERVER_PORT);

Reply via email to