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

NIFI-7584-rebase-squash Added a POST request to the OIDC revoke endpo… #4582

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -422,5 +422,23 @@
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.4</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package org.apache.nifi.web;

import java.util.Arrays;
import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.web.security.anonymous.NiFiAnonymousAuthenticationFilter;
import org.apache.nifi.web.security.anonymous.NiFiAnonymousAuthenticationProvider;
Expand Down Expand Up @@ -48,8 +49,6 @@
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
* NiFi Web Api Spring security. Applies the various NiFiAuthenticationFilter servlet filters which will extract authentication
* credentials from API requests.
Expand Down Expand Up @@ -92,7 +91,7 @@ public void configure(WebSecurity webSecurity) throws Exception {
webSecurity
.ignoring()
.antMatchers("/access", "/access/config", "/access/token", "/access/kerberos",
"/access/oidc/exchange", "/access/oidc/callback", "/access/oidc/request",
"/access/oidc/exchange", "/access/oidc/callback", "/access/oidc/logoutCallback", "/access/oidc/request",
"/access/knox/callback", "/access/knox/request");
}

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.nimbusds.oauth2.sdk.id.ClientID;
import java.io.IOException;
import java.net.URI;
import org.apache.nifi.web.security.token.LoginAuthenticationToken;

public interface OidcIdentityProvider {

Expand Down Expand Up @@ -60,6 +61,13 @@ public interface OidcIdentityProvider {
*/
URI getEndSessionEndpoint();

/**
* Returns the URI for the revocation endpoint.
*
* @return uri for the revocation endpoint
*/
URI getRevocationEndpoint();

/**
* Returns the scopes supported by the OIDC provider.
*
Expand All @@ -68,12 +76,30 @@ public interface OidcIdentityProvider {
Scope getScope();

/**
* Exchanges the supplied authorization grant for an ID token. Extracts the identity from the ID
* token and converts it into NiFi JWT.
* Exchanges the supplied authorization grant for a Login ID Token. Extracts the identity from the ID
* token.
*
* @param authorizationGrant authorization grant for invoking the Token Endpoint
* @return a Login Authentication Token
* @throws IOException if there was an exceptional error while communicating with the OIDC provider
*/
LoginAuthenticationToken exchangeAuthorizationCodeforLoginAuthenticationToken(AuthorizationGrant authorizationGrant) throws IOException;

/**
* Exchanges the supplied authorization grant for an Access Token.
*
* @param authorizationGrant authorization grant for invoking the Token Endpoint
* @return an Access Token String
* @throws Exception if there was an exceptional error while communicating with the OIDC provider
*/
String exchangeAuthorizationCodeForAccessToken(AuthorizationGrant authorizationGrant) throws Exception;

/**
* Exchanges the supplied authorization grant for an ID Token.
*
* @param authorizationGrant authorization grant for invoking the Token Endpoint
* @return a NiFi JWT
* @return an ID Token String
* @throws IOException if there was an exceptional error while communicating with the OIDC provider
*/
String exchangeAuthorizationCode(AuthorizationGrant authorizationGrant) throws IOException;
String exchangeAuthorizationCodeForIdToken(final AuthorizationGrant authorizationGrant) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.security.SecureRandom;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.apache.nifi.web.security.token.LoginAuthenticationToken;
import org.apache.nifi.web.security.util.CacheKey;

import static org.apache.nifi.web.security.oidc.StandardOidcIdentityProvider.OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED;
Expand Down Expand Up @@ -98,6 +99,15 @@ public URI getEndSessionEndpoint() {
return identityProvider.getEndSessionEndpoint();
}

/**
* Returns the OpenId Connect revocation endpoint.
*
* @return the revocation endpoint
*/
public URI getRevocationEndpoint() {
return identityProvider.getRevocationEndpoint();
}

/**
* Returns the OpenId Connect scope.
*
Expand Down Expand Up @@ -186,42 +196,72 @@ public boolean isStateValid(final String oidcRequestIdentifier, final State prop
}

/**
* Exchanges the specified authorization grant for an ID token for the given request identifier.
* Exchanges the specified authorization grant for an ID token.
*
* @param oidcRequestIdentifier request identifier
* @param authorizationGrant authorization grant
* @return a Login Authentication Token
* @throws IOException exceptional case for communication error with the OpenId Connect provider
*/
public void exchangeAuthorizationCode(final String oidcRequestIdentifier, final AuthorizationGrant authorizationGrant) throws IOException {
public LoginAuthenticationToken exchangeAuthorizationCodeForLoginAuthenticationToken(final AuthorizationGrant authorizationGrant) throws IOException {
if (!isOidcEnabled()) {
throw new IllegalStateException(OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED);
}

final CacheKey oidcRequestIdentifierKey = new CacheKey(oidcRequestIdentifier);
final String nifiJwt = retrieveNifiJwt(authorizationGrant);
// Retrieve Login Authentication Token
return identityProvider.exchangeAuthorizationCodeforLoginAuthenticationToken(authorizationGrant);
}

try {
// cache the jwt for later retrieval
synchronized (jwtLookupForCompletedRequests) {
final String cachedJwt = jwtLookupForCompletedRequests.get(oidcRequestIdentifierKey, () -> nifiJwt);
if (!timeConstantEqualityCheck(nifiJwt, cachedJwt)) {
throw new IllegalStateException("An existing login request is already in progress.");
}
}
} catch (final ExecutionException e) {
throw new IllegalStateException("Unable to store the login authentication token.");
/**
* Exchanges the specified authorization grant for an access token.
*
* @param authorizationGrant authorization grant
* @return an Access Token string
* @throws IOException exceptional case for communication error with the OpenId Connect provider
*/
public String exchangeAuthorizationCodeForAccessToken(final AuthorizationGrant authorizationGrant) throws Exception {
if (!isOidcEnabled()) {
throw new IllegalStateException(OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED);
}

// Retrieve access token
return identityProvider.exchangeAuthorizationCodeForAccessToken(authorizationGrant);
}

/**
* Exchange the authorization code to retrieve a NiFi JWT.
* Exchanges the specified authorization grant for an ID Token.
*
* @param authorizationGrant authorization grant
* @return NiFi JWT
* @return an ID Token string
* @throws IOException exceptional case for communication error with the OpenId Connect provider
*/
public String retrieveNifiJwt(final AuthorizationGrant authorizationGrant) throws IOException {
return identityProvider.exchangeAuthorizationCode(authorizationGrant);
public String exchangeAuthorizationCodeForIdToken(final AuthorizationGrant authorizationGrant) throws IOException {
if (!isOidcEnabled()) {
throw new IllegalStateException(OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED);
}

// Retrieve ID token
return identityProvider.exchangeAuthorizationCodeForIdToken(authorizationGrant);
}

/**
* Stores the NiFi Jwt.
*
* @param oidcRequestIdentifier request identifier
* @param jwt NiFi JWT
*/
public void storeJwt(final String oidcRequestIdentifier, final String jwt) {
final CacheKey oidcRequestIdentifierKey = new CacheKey(oidcRequestIdentifier);
try {
// Cache the jwt for later retrieval
synchronized (jwtLookupForCompletedRequests) {
final String cachedJwt = jwtLookupForCompletedRequests.get(oidcRequestIdentifierKey, () -> jwt);
if (!timeConstantEqualityCheck(jwt, cachedJwt)) {
throw new IllegalStateException("An existing login request is already in progress.");
}
}
} catch (final ExecutionException e) {
throw new IllegalStateException("Unable to store the login authentication token.");
}
}

/**
Expand Down