thenatog commented on a change in pull request #4593:
URL: https://github.com/apache/nifi/pull/4593#discussion_r504218997
##########
File path:
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
##########
@@ -329,24 +359,221 @@ public Response oidcExchange(@Context HttpServletRequest
httpServletRequest, @Co
)
public void oidcLogout(@Context HttpServletRequest httpServletRequest,
@Context HttpServletResponse httpServletResponse) throws Exception {
if (!httpServletRequest.isSecure()) {
- throw new IllegalStateException("User authentication/authorization
is only supported when running over HTTPS.");
+ throw new IllegalStateException(AUTHENTICATION_NOT_ENABLED_MSG);
}
if (!oidcService.isOidcEnabled()) {
- throw new IllegalStateException("OpenId Connect is not
configured.");
+ throw new
IllegalStateException(OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED_MSG);
}
- URI endSessionEndpoint = oidcService.getEndSessionEndpoint();
- String postLogoutRedirectUri = generateResourceUri("..", "nifi",
"logout-complete");
+ // Get the oidc discovery url
+ String oidcDiscoveryUrl = properties.getOidcDiscoveryUrl();
+
+ // Determine the logout method
+ String logoutMethod = determineLogoutMethod(oidcDiscoveryUrl);
+
+ switch (logoutMethod) {
+ case REVOKE_ACCESS_TOKEN_LOGOUT:
+ case ID_TOKEN_LOGOUT:
+ // Make a request to the IdP
+ URI authorizationURI =
oidcRequestAuthorizationCode(httpServletResponse, getOidcLogoutCallback());
+ httpServletResponse.sendRedirect(authorizationURI.toString());
+ break;
+ case STANDARD_LOGOUT:
+ default:
+ // Get the OIDC end session endpoint
+ URI endSessionEndpoint = oidcService.getEndSessionEndpoint();
+ String postLogoutRedirectUri = generateResourceUri( "..",
"nifi", "logout-complete");
+
+ if (endSessionEndpoint == null) {
+ httpServletResponse.sendRedirect(postLogoutRedirectUri);
+ } else {
+ URI logoutUri = UriBuilder.fromUri(endSessionEndpoint)
+ .queryParam("post_logout_redirect_uri",
postLogoutRedirectUri)
+ .build();
+ httpServletResponse.sendRedirect(logoutUri.toString());
+ }
+ break;
+ }
+ }
- if (endSessionEndpoint == null) {
- // handle the case, where the OpenID Provider does not have an end
session endpoint
- httpServletResponse.sendRedirect(postLogoutRedirectUri);
+ @GET
+ @Consumes(MediaType.WILDCARD)
+ @Produces(MediaType.WILDCARD)
+ @Path("oidc/logoutCallback")
+ @ApiOperation(
+ value = "Redirect/callback URI for processing the result of the
OpenId Connect logout sequence.",
+ notes = NON_GUARANTEED_ENDPOINT
+ )
+ public void oidcLogoutCallback(@Context HttpServletRequest
httpServletRequest, @Context HttpServletResponse httpServletResponse) throws
Exception {
+ // only consider user specific access over https
+ if (!httpServletRequest.isSecure()) {
+ forwardToMessagePage(httpServletRequest, httpServletResponse,
AUTHENTICATION_NOT_ENABLED_MSG);
+ return;
+ }
+
+ // ensure oidc is enabled
+ if (!oidcService.isOidcEnabled()) {
+ forwardToMessagePage(httpServletRequest, httpServletResponse,
OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED_MSG);
+ return;
+ }
+
+ final String oidcRequestIdentifier =
getCookieValue(httpServletRequest.getCookies(), OIDC_REQUEST_IDENTIFIER);
+ if (oidcRequestIdentifier == null) {
+ forwardToMessagePage(httpServletRequest, httpServletResponse, "The
login request identifier was not found in the request. Unable to continue.");
+ return;
+ }
+
+ final com.nimbusds.openid.connect.sdk.AuthenticationResponse
oidcResponse;
+ try {
+ oidcResponse = AuthenticationResponseParser.parse(getRequestUri());
+ } catch (final ParseException e) {
+ logger.error("Unable to parse the redirect URI from the OpenId
Connect Provider. Unable to continue logout process.");
+
+ // remove the oidc request cookie
+ removeOidcRequestCookie(httpServletResponse);
+
+ // forward to the error page
+ forwardToMessagePage(httpServletRequest, httpServletResponse,
"Unable to parse the redirect URI from the OpenId Connect Provider. Unable to
continue logout process.");
+ return;
+ }
+
+ if (oidcResponse.indicatesSuccess()) {
+ final AuthenticationSuccessResponse successfulOidcResponse =
(AuthenticationSuccessResponse) oidcResponse;
+
+ // confirm state
+ final State state = successfulOidcResponse.getState();
+ if (state == null ||
!oidcService.isStateValid(oidcRequestIdentifier, state)) {
+ logger.error("The state value returned by the OpenId Connect
Provider does not match the stored state. Unable to continue login process.");
+
+ // remove the oidc request cookie
+ removeOidcRequestCookie(httpServletResponse);
+
+ // forward to the error page
+ forwardToMessagePage(httpServletRequest, httpServletResponse,
"Purposed state does not match the stored state. Unable to continue login
process.");
+ return;
+ }
+
+ // Get the oidc discovery url
+ String oidcDiscoveryUrl = properties.getOidcDiscoveryUrl();
+
+ // Determine which logout method to use
+ String logoutMethod = determineLogoutMethod(oidcDiscoveryUrl);
+
+ // Get the authorization code and grant
+ final AuthorizationCode authorizationCode =
successfulOidcResponse.getAuthorizationCode();
+ final AuthorizationGrant authorizationGrant = new
AuthorizationCodeGrant(authorizationCode, URI.create(getOidcLogoutCallback()));
+
+ switch (logoutMethod) {
+ case REVOKE_ACCESS_TOKEN_LOGOUT:
+ // Use the Revocation endpoint + access token
+ final String accessToken;
+ try {
+ // Return the access token
+ accessToken =
oidcService.exchangeAuthorizationCodeForAccessToken(authorizationGrant);
+ } catch (final Exception e) {
+ logger.error("Unable to exchange authorization for the
Access token: " + e.getMessage(), e);
+
+ // Remove the oidc request cookie
+ removeOidcRequestCookie(httpServletResponse);
+
+ // Forward to the error page
+ forwardToMessagePage(httpServletRequest,
httpServletResponse, "Unable to exchange " +
+ "authorization for ID token: " +
e.getMessage());
+ return;
+ }
+
+ // Build the revoke URI and send the POST request
+ URI revokeEndpoint = getRevokeEndpoint();
+
+ if (revokeEndpoint != null) {
+ try {
Review comment:
Is there a reason this section of code to POST to the revoke endpoint
can't be extracted to a private method? This is a big chunk of code that has a
specific purpose.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]