| /* |
| * 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.api; |
| |
| import com.nimbusds.oauth2.sdk.AuthorizationCode; |
| import com.nimbusds.oauth2.sdk.AuthorizationCodeGrant; |
| import com.nimbusds.oauth2.sdk.AuthorizationGrant; |
| import com.nimbusds.oauth2.sdk.ParseException; |
| import com.nimbusds.oauth2.sdk.http.HTTPResponse; |
| import com.nimbusds.oauth2.sdk.id.State; |
| import com.nimbusds.openid.connect.sdk.AuthenticationErrorResponse; |
| import com.nimbusds.openid.connect.sdk.AuthenticationResponse; |
| import com.nimbusds.openid.connect.sdk.AuthenticationResponseParser; |
| import com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse; |
| import io.swagger.annotations.Api; |
| import io.swagger.annotations.ApiOperation; |
| import org.apache.http.NameValuePair; |
| import org.apache.http.client.config.RequestConfig; |
| import org.apache.http.client.entity.UrlEncodedFormEntity; |
| import org.apache.http.client.methods.CloseableHttpResponse; |
| import org.apache.http.client.methods.HttpPost; |
| import org.apache.http.impl.client.CloseableHttpClient; |
| import org.apache.http.impl.client.HttpClientBuilder; |
| import org.apache.http.message.BasicNameValuePair; |
| import org.apache.nifi.authentication.exception.AuthenticationNotSupportedException; |
| import org.apache.nifi.authorization.user.NiFiUserUtils; |
| import org.apache.nifi.util.NiFiProperties; |
| import org.apache.nifi.web.security.jwt.JwtService; |
| import org.apache.nifi.web.security.jwt.NiFiBearerTokenResolver; |
| import org.apache.nifi.web.security.oidc.OIDCEndpoints; |
| import org.apache.nifi.web.security.oidc.OidcService; |
| import org.apache.nifi.web.security.token.LoginAuthenticationToken; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.springframework.web.util.WebUtils; |
| |
| import javax.annotation.PreDestroy; |
| import javax.servlet.http.Cookie; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import javax.ws.rs.Consumes; |
| import javax.ws.rs.GET; |
| import javax.ws.rs.POST; |
| import javax.ws.rs.Path; |
| import javax.ws.rs.Produces; |
| import javax.ws.rs.core.Context; |
| import javax.ws.rs.core.MediaType; |
| import javax.ws.rs.core.Response; |
| import javax.ws.rs.core.UriBuilder; |
| import java.io.IOException; |
| import java.net.URI; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.UUID; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| |
| @Path(OIDCEndpoints.OIDC_ACCESS_ROOT) |
| @Api( |
| value = OIDCEndpoints.OIDC_ACCESS_ROOT, |
| description = "Endpoints for obtaining an access token or checking access status." |
| ) |
| public class OIDCAccessResource extends AccessResource { |
| |
| private static final Logger logger = LoggerFactory.getLogger(OIDCAccessResource.class); |
| private static final String OIDC_REQUEST_IDENTIFIER = "oidc-request-identifier"; |
| private static final String OIDC_ID_TOKEN_AUTHN_ERROR = "Unable to exchange authorization for ID token: "; |
| private static final String OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED_MSG = "OpenId Connect support is not configured"; |
| private static final String REVOKE_ACCESS_TOKEN_LOGOUT = "oidc_access_token_logout"; |
| private static final String ID_TOKEN_LOGOUT = "oidc_id_token_logout"; |
| private static final String STANDARD_LOGOUT = "oidc_standard_logout"; |
| private static final Pattern REVOKE_ACCESS_TOKEN_LOGOUT_FORMAT = Pattern.compile("(\\.google\\.com)"); |
| private static final Pattern ID_TOKEN_LOGOUT_FORMAT = Pattern.compile("(\\.okta)"); |
| private static final int msTimeout = 30_000; |
| private static final boolean LOGGING_IN = true; |
| |
| private OidcService oidcService; |
| private JwtService jwtService; |
| private CloseableHttpClient httpClient; |
| |
| public OIDCAccessResource() { |
| RequestConfig config = RequestConfig.custom() |
| .setConnectTimeout(msTimeout) |
| .setConnectionRequestTimeout(msTimeout) |
| .setSocketTimeout(msTimeout) |
| .build(); |
| |
| httpClient = HttpClientBuilder |
| .create() |
| .setDefaultRequestConfig(config) |
| .build(); |
| } |
| |
| @GET |
| @Consumes(MediaType.WILDCARD) |
| @Produces(MediaType.WILDCARD) |
| @Path(OIDCEndpoints.LOGIN_REQUEST_RELATIVE) |
| @ApiOperation( |
| value = "Initiates a request to authenticate through the configured OpenId Connect provider.", |
| notes = NON_GUARANTEED_ENDPOINT |
| ) |
| public void oidcRequest(@Context HttpServletRequest httpServletRequest, @Context HttpServletResponse httpServletResponse) throws Exception { |
| // only consider user specific access over https |
| if (!httpServletRequest.isSecure()) { |
| forwardToLoginMessagePage(httpServletRequest, httpServletResponse, AUTHENTICATION_NOT_ENABLED_MSG); |
| return; |
| } |
| |
| // ensure oidc is enabled |
| if (!oidcService.isOidcEnabled()) { |
| forwardToLoginMessagePage(httpServletRequest, httpServletResponse, OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED_MSG); |
| return; |
| } |
| |
| // generate the authorization uri |
| URI authorizationURI = oidcRequestAuthorizationCode(httpServletResponse, getOidcCallback()); |
| |
| // generate the response |
| httpServletResponse.sendRedirect(authorizationURI.toString()); |
| } |
| |
| @GET |
| @Consumes(MediaType.WILDCARD) |
| @Produces(MediaType.WILDCARD) |
| @Path(OIDCEndpoints.LOGIN_CALLBACK_RELATIVE) |
| @ApiOperation( |
| value = "Redirect/callback URI for processing the result of the OpenId Connect login sequence.", |
| notes = NON_GUARANTEED_ENDPOINT |
| ) |
| public void oidcCallback(@Context HttpServletRequest httpServletRequest, @Context HttpServletResponse httpServletResponse) throws Exception { |
| final AuthenticationResponse oidcResponse = parseOidcResponse(httpServletRequest, httpServletResponse, LOGGING_IN); |
| |
| final String oidcRequestIdentifier = WebUtils.getCookie(httpServletRequest, OIDC_REQUEST_IDENTIFIER).getValue(); |
| |
| if (oidcResponse != null && oidcResponse.indicatesSuccess()) { |
| final AuthenticationSuccessResponse successfulOidcResponse = (AuthenticationSuccessResponse) oidcResponse; |
| |
| checkOidcState(httpServletResponse, oidcRequestIdentifier, successfulOidcResponse, LOGGING_IN); |
| |
| try { |
| // exchange authorization code for id token |
| final AuthorizationCode authorizationCode = successfulOidcResponse.getAuthorizationCode(); |
| final AuthorizationGrant authorizationGrant = new AuthorizationCodeGrant(authorizationCode, URI.create(getOidcCallback())); |
| |
| // get the oidc token |
| LoginAuthenticationToken oidcToken = oidcService.exchangeAuthorizationCodeForLoginAuthenticationToken(authorizationGrant); |
| |
| // exchange the oidc token for the NiFi token |
| String nifiJwt = jwtService.generateSignedToken(oidcToken); |
| |
| // store the NiFi token |
| oidcService.storeJwt(oidcRequestIdentifier, nifiJwt); |
| } catch (final Exception e) { |
| logger.error(OIDC_ID_TOKEN_AUTHN_ERROR + e.getMessage(), e); |
| |
| // remove the oidc request cookie |
| removeOidcRequestCookie(httpServletResponse); |
| |
| // forward to the error page |
| forwardToLoginMessagePage(httpServletRequest, httpServletResponse, OIDC_ID_TOKEN_AUTHN_ERROR + e.getMessage()); |
| return; |
| } |
| |
| // redirect to the name page |
| httpServletResponse.sendRedirect(getNiFiUri()); |
| } else { |
| // remove the oidc request cookie |
| removeOidcRequestCookie(httpServletResponse); |
| |
| // report the unsuccessful login |
| final AuthenticationErrorResponse errorOidcResponse = (AuthenticationErrorResponse) oidcResponse; |
| forwardToLoginMessagePage(httpServletRequest, httpServletResponse, "Unsuccessful login attempt: " |
| + errorOidcResponse.getErrorObject().getDescription()); |
| } |
| } |
| |
| @POST |
| @Consumes(MediaType.WILDCARD) |
| @Produces(MediaType.TEXT_PLAIN) |
| @Path(OIDCEndpoints.TOKEN_EXCHANGE_RELATIVE) |
| @ApiOperation( |
| value = "Retrieves a JWT following a successful login sequence using the configured OpenId Connect provider.", |
| response = String.class, |
| notes = NON_GUARANTEED_ENDPOINT |
| ) |
| public Response oidcExchange(@Context HttpServletRequest httpServletRequest, @Context HttpServletResponse httpServletResponse) { |
| // only consider user specific access over https |
| if (!httpServletRequest.isSecure()) { |
| throw new AuthenticationNotSupportedException(AUTHENTICATION_NOT_ENABLED_MSG); |
| } |
| |
| // ensure oidc is enabled |
| if (!oidcService.isOidcEnabled()) { |
| logger.debug(OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED_MSG); |
| return Response.status(Response.Status.CONFLICT).entity(OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED_MSG).build(); |
| } |
| |
| final String oidcRequestIdentifier = WebUtils.getCookie(httpServletRequest, OIDC_REQUEST_IDENTIFIER).getValue(); |
| if (oidcRequestIdentifier == null) { |
| final String message = "The login request identifier was not found in the request. Unable to continue."; |
| logger.warn(message); |
| return Response.status(Response.Status.BAD_REQUEST).entity(message).build(); |
| } |
| |
| // remove the oidc request cookie |
| removeOidcRequestCookie(httpServletResponse); |
| |
| // get the jwt |
| final String jwt = oidcService.getJwt(oidcRequestIdentifier); |
| if (jwt == null) { |
| throw new IllegalArgumentException("A JWT for this login request identifier could not be found. Unable to continue."); |
| } |
| |
| return generateTokenResponse(generateOkResponse(jwt), jwt); |
| } |
| |
| @GET |
| @Consumes(MediaType.WILDCARD) |
| @Produces(MediaType.WILDCARD) |
| @Path(OIDCEndpoints.LOGOUT_REQUEST_RELATIVE) |
| @ApiOperation( |
| value = "Performs a logout in the OpenId Provider.", |
| notes = NON_GUARANTEED_ENDPOINT |
| ) |
| public void oidcLogout(@Context HttpServletRequest httpServletRequest, @Context HttpServletResponse httpServletResponse) throws Exception { |
| if (!httpServletRequest.isSecure()) { |
| throw new IllegalStateException(AUTHENTICATION_NOT_ENABLED_MSG); |
| } |
| |
| if (!oidcService.isOidcEnabled()) { |
| throw new IllegalStateException(OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED_MSG); |
| } |
| |
| final String mappedUserIdentity = NiFiUserUtils.getNiFiUserIdentity(); |
| removeCookie(httpServletResponse, NiFiBearerTokenResolver.JWT_COOKIE_NAME); |
| logger.debug("Invalidated JWT for user [{}]", mappedUserIdentity); |
| |
| // 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; |
| } |
| } |
| |
| @GET |
| @Consumes(MediaType.WILDCARD) |
| @Produces(MediaType.WILDCARD) |
| @Path(OIDCEndpoints.LOGOUT_CALLBACK_RELATIVE) |
| @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 { |
| final AuthenticationResponse oidcResponse = parseOidcResponse(httpServletRequest, httpServletResponse, !LOGGING_IN); |
| |
| final String oidcRequestIdentifier = WebUtils.getCookie(httpServletRequest, OIDC_REQUEST_IDENTIFIER).getValue(); |
| |
| if (oidcResponse != null && oidcResponse.indicatesSuccess()) { |
| final AuthenticationSuccessResponse successfulOidcResponse = (AuthenticationSuccessResponse) oidcResponse; |
| |
| // confirm state |
| checkOidcState(httpServletResponse, oidcRequestIdentifier, successfulOidcResponse, false); |
| |
| // 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 |
| forwardToLogoutMessagePage(httpServletRequest, httpServletResponse, OIDC_ID_TOKEN_AUTHN_ERROR + e.getMessage()); |
| return; |
| } |
| |
| // Build the revoke URI and send the POST request |
| URI revokeEndpoint = getRevokeEndpoint(); |
| |
| if (revokeEndpoint != null) { |
| try { |
| // Logout with the revoke endpoint |
| revokeEndpointRequest(httpServletResponse, accessToken, revokeEndpoint); |
| |
| } catch (final IOException e) { |
| logger.error("There was an error logging out of the OpenId Connect Provider: " |
| + e.getMessage(), e); |
| |
| // Remove the oidc request cookie |
| removeOidcRequestCookie(httpServletResponse); |
| |
| // Forward to the error page |
| forwardToLogoutMessagePage(httpServletRequest, httpServletResponse, |
| "There was an error logging out of the OpenId Connect Provider: " |
| + e.getMessage()); |
| } |
| } |
| break; |
| case ID_TOKEN_LOGOUT: |
| // Use the end session endpoint + ID Token |
| final String idToken; |
| try { |
| // Return the ID Token |
| idToken = oidcService.exchangeAuthorizationCodeForIdToken(authorizationGrant); |
| } catch (final Exception e) { |
| logger.error(OIDC_ID_TOKEN_AUTHN_ERROR + e.getMessage(), e); |
| |
| // Remove the oidc request cookie |
| removeOidcRequestCookie(httpServletResponse); |
| |
| // Forward to the error page |
| forwardToLogoutMessagePage(httpServletRequest, httpServletResponse, OIDC_ID_TOKEN_AUTHN_ERROR + e.getMessage()); |
| return; |
| } |
| |
| // Get the OIDC end session endpoint |
| URI endSessionEndpoint = oidcService.getEndSessionEndpoint(); |
| String postLogoutRedirectUri = generateResourceUri("..", "nifi", "logout-complete"); |
| |
| if (endSessionEndpoint == null) { |
| logger.debug("Unable to log out of the OpenId Connect Provider. The end session endpoint is: null." + |
| " Redirecting to the logout page."); |
| httpServletResponse.sendRedirect(postLogoutRedirectUri); |
| } else { |
| URI logoutUri = UriBuilder.fromUri(endSessionEndpoint) |
| .queryParam("id_token_hint", idToken) |
| .queryParam("post_logout_redirect_uri", postLogoutRedirectUri) |
| .build(); |
| httpServletResponse.sendRedirect(logoutUri.toString()); |
| } |
| break; |
| } |
| } else { |
| // remove the oidc request cookie |
| removeOidcRequestCookie(httpServletResponse); |
| |
| // report the unsuccessful logout |
| final AuthenticationErrorResponse errorOidcResponse = (AuthenticationErrorResponse) oidcResponse; |
| forwardToLogoutMessagePage(httpServletRequest, httpServletResponse, "Unsuccessful logout attempt: " |
| + errorOidcResponse.getErrorObject().getDescription()); |
| } |
| } |
| |
| /** |
| * Generates the request Authorization URI for the OpenID Connect Provider. Returns an authorization |
| * URI using the provided callback URI. |
| * |
| * @param httpServletResponse the servlet response |
| * @param callback the OIDC callback URI |
| * @return the authorization URI |
| */ |
| private URI oidcRequestAuthorizationCode(@Context HttpServletResponse httpServletResponse, String callback) { |
| |
| final String oidcRequestIdentifier = UUID.randomUUID().toString(); |
| |
| // generate a cookie to associate this login sequence |
| final Cookie cookie = new Cookie(OIDC_REQUEST_IDENTIFIER, oidcRequestIdentifier); |
| cookie.setPath("/"); |
| cookie.setHttpOnly(true); |
| cookie.setMaxAge(60); |
| cookie.setSecure(true); |
| httpServletResponse.addCookie(cookie); |
| |
| // get the state for this request |
| final State state = oidcService.createState(oidcRequestIdentifier); |
| |
| // build the authorization uri |
| final URI authorizationUri = UriBuilder.fromUri(oidcService.getAuthorizationEndpoint()) |
| .queryParam("client_id", oidcService.getClientId()) |
| .queryParam("response_type", "code") |
| .queryParam("scope", oidcService.getScope().toString()) |
| .queryParam("state", state.getValue()) |
| .queryParam("redirect_uri", callback) |
| .build(); |
| |
| // return Authorization URI |
| return authorizationUri; |
| } |
| |
| private String determineLogoutMethod(String oidcDiscoveryUrl) { |
| Matcher accessTokenMatcher = REVOKE_ACCESS_TOKEN_LOGOUT_FORMAT.matcher(oidcDiscoveryUrl); |
| Matcher idTokenMatcher = ID_TOKEN_LOGOUT_FORMAT.matcher(oidcDiscoveryUrl); |
| |
| if (accessTokenMatcher.find()) { |
| return REVOKE_ACCESS_TOKEN_LOGOUT; |
| } else if (idTokenMatcher.find()) { |
| return ID_TOKEN_LOGOUT; |
| } else { |
| return STANDARD_LOGOUT; |
| } |
| } |
| |
| /** |
| * Sends a POST request to the revoke endpoint to log out of the ID Provider. |
| * |
| * @param httpServletResponse the servlet response |
| * @param accessToken the OpenID Connect Provider access token |
| * @param revokeEndpoint the name of the cookie |
| * @throws IOException exceptional case for communication error with the OpenId Connect Provider |
| */ |
| private void revokeEndpointRequest(@Context HttpServletResponse httpServletResponse, String accessToken, URI revokeEndpoint) throws IOException { |
| |
| HttpPost httpPost = new HttpPost(revokeEndpoint); |
| |
| List<NameValuePair> params = new ArrayList<>(); |
| // Append a query param with the access token |
| params.add(new BasicNameValuePair("token", accessToken)); |
| httpPost.setEntity(new UrlEncodedFormEntity(params)); |
| |
| try (CloseableHttpResponse response = httpClient.execute(httpPost)) { |
| if (response.getStatusLine().getStatusCode() == HTTPResponse.SC_OK) { |
| // Redirect to logout page |
| logger.debug("You are logged out of the OpenId Connect Provider."); |
| String postLogoutRedirectUri = generateResourceUri("..", "nifi", "logout-complete"); |
| httpServletResponse.sendRedirect(postLogoutRedirectUri); |
| } else { |
| logger.error("There was an error logging out of the OpenId Connect Provider. " + |
| "Response status: " + response.getStatusLine().getStatusCode()); |
| } |
| } |
| } |
| |
| @PreDestroy |
| private final void closeClient() throws IOException { |
| httpClient.close(); |
| } |
| |
| private AuthenticationResponse parseOidcResponse(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, boolean isLogin) throws Exception { |
| final String pageTitle = getForwardPageTitle(isLogin); |
| |
| // only consider user specific access over https |
| if (!httpServletRequest.isSecure()) { |
| forwardToMessagePage(httpServletRequest, httpServletResponse, pageTitle, AUTHENTICATION_NOT_ENABLED_MSG); |
| return null; |
| } |
| |
| // ensure oidc is enabled |
| if (!oidcService.isOidcEnabled()) { |
| forwardToMessagePage(httpServletRequest, httpServletResponse, pageTitle, OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED_MSG); |
| return null; |
| } |
| |
| final String oidcRequestIdentifier = WebUtils.getCookie(httpServletRequest, OIDC_REQUEST_IDENTIFIER).getValue(); |
| if (oidcRequestIdentifier == null) { |
| forwardToMessagePage(httpServletRequest, httpServletResponse, pageTitle,"The request identifier was " + |
| "not found in the request. Unable to continue."); |
| return null; |
| } |
| |
| final com.nimbusds.openid.connect.sdk.AuthenticationResponse oidcResponse; |
| try { |
| oidcResponse = AuthenticationResponseParser.parse(getRequestUri()); |
| return oidcResponse; |
| } catch (final ParseException e) { |
| logger.error("Unable to parse the redirect URI from the OpenId Connect Provider. Unable to continue login/logout process."); |
| |
| // remove the oidc request cookie |
| removeOidcRequestCookie(httpServletResponse); |
| |
| // forward to the error page |
| forwardToMessagePage(httpServletRequest, httpServletResponse, pageTitle,"Unable to parse the redirect URI " + |
| "from the OpenId Connect Provider. Unable to continue login/logout process."); |
| return null; |
| } |
| } |
| |
| private void checkOidcState(HttpServletResponse httpServletResponse, final String oidcRequestIdentifier, AuthenticationSuccessResponse successfulOidcResponse, boolean isLogin) throws Exception { |
| // 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/logout process."); |
| |
| // remove the oidc request cookie |
| removeOidcRequestCookie(httpServletResponse); |
| |
| // forward to the error page |
| forwardToMessagePage(httpServletRequest, httpServletResponse, getForwardPageTitle(isLogin), "Purposed state does not match " + |
| "the stored state. Unable to continue login/logout process."); |
| return; |
| } |
| } |
| |
| private String getForwardPageTitle(boolean isLogin) { |
| return isLogin ? ApplicationResource.LOGIN_ERROR_TITLE : ApplicationResource.LOGOUT_ERROR_TITLE; |
| } |
| |
| private String getOidcCallback() { |
| return generateResourceUri("access", "oidc", "callback"); |
| } |
| |
| private String getOidcLogoutCallback() { |
| return generateResourceUri("access", "oidc", "logoutCallback"); |
| } |
| |
| private URI getRevokeEndpoint() { |
| return oidcService.getRevocationEndpoint(); |
| } |
| |
| private void removeOidcRequestCookie(final HttpServletResponse httpServletResponse) { |
| removeCookie(httpServletResponse, OIDC_REQUEST_IDENTIFIER); |
| } |
| |
| public void setOidcService(OidcService oidcService) { |
| this.oidcService = oidcService; |
| } |
| |
| public void setJwtService(JwtService jwtService) { |
| this.jwtService = jwtService; |
| } |
| |
| public void setProperties(final NiFiProperties properties) { |
| this.properties = properties; |
| } |
| |
| protected NiFiProperties getProperties() { |
| return properties; |
| } |
| } |