[ https://issues.apache.org/jira/browse/NIFI-4210?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16111380#comment-16111380
]
ASF GitHub Bot commented on NIFI-4210:
--------------------------------------
Github user mcgilman commented on a diff in the pull request:
https://github.com/apache/nifi/pull/2047#discussion_r130943341
--- Diff: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/StandardOidcIdentityProvider.java
---
@@ -0,0 +1,339 @@
+/*
+ * 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.oidc;
+
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.proc.BadJOSEException;
+import com.nimbusds.jose.util.DefaultResourceRetriever;
+import com.nimbusds.jose.util.ResourceRetriever;
+import com.nimbusds.jwt.JWT;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.oauth2.sdk.AuthorizationGrant;
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.Scope;
+import com.nimbusds.oauth2.sdk.TokenErrorResponse;
+import com.nimbusds.oauth2.sdk.TokenRequest;
+import com.nimbusds.oauth2.sdk.TokenResponse;
+import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
+import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
+import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic;
+import com.nimbusds.oauth2.sdk.auth.ClientSecretPost;
+import com.nimbusds.oauth2.sdk.auth.Secret;
+import com.nimbusds.oauth2.sdk.http.HTTPRequest;
+import com.nimbusds.oauth2.sdk.http.HTTPResponse;
+import com.nimbusds.oauth2.sdk.id.ClientID;
+import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
+import com.nimbusds.openid.connect.sdk.OIDCScopeValue;
+import com.nimbusds.openid.connect.sdk.OIDCTokenResponse;
+import com.nimbusds.openid.connect.sdk.OIDCTokenResponseParser;
+import com.nimbusds.openid.connect.sdk.UserInfoErrorResponse;
+import com.nimbusds.openid.connect.sdk.UserInfoRequest;
+import com.nimbusds.openid.connect.sdk.UserInfoResponse;
+import com.nimbusds.openid.connect.sdk.UserInfoSuccessResponse;
+import com.nimbusds.openid.connect.sdk.claims.IDTokenClaimsSet;
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+import com.nimbusds.openid.connect.sdk.token.OIDCTokens;
+import com.nimbusds.openid.connect.sdk.validators.IDTokenValidator;
+import net.minidev.json.JSONObject;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.util.FormatUtils;
+import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.web.security.jwt.JwtService;
+import org.apache.nifi.web.security.token.LoginAuthenticationToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import static com.nimbusds.openid.connect.sdk.claims.UserInfo.EMAIL_CLAIM_NAME;
+
+/**
+ * OidcProvider for managing the OpenId Connect Authorization flow.
+ */
+public class StandardOidcIdentityProvider implements OidcIdentityProvider {
+
+ private static final Logger logger = LoggerFactory.getLogger(StandardOidcIdentityProvider.class);
+
+ private NiFiProperties properties;
+ private JwtService jwtService;
+ private OIDCProviderMetadata oidcProviderMetadata;
+ private int oidcConnectTimeout;
+ private int oidcReadTimeout;
+ private IDTokenValidator tokenValidator;
+ private ClientID clientId;
+ private Secret clientSecret;
+
+ /**
+ * Creates a new StandardOidcIdentityProvider.
+ *
+ * @param jwtService jwt service
+ * @param properties properties
+ */
+ public StandardOidcIdentityProvider(final JwtService jwtService, final NiFiProperties
properties) {
+ this.properties = properties;
+ this.jwtService = jwtService;
+
+ // attempt to process the oidc configuration if configured
+ if (properties.isOidcEnabled()) {
+ // oidc connect timeout
+ final String rawConnectTimeout = properties.getOidcConnectTimeout();
+ try {
+ oidcConnectTimeout = (int) FormatUtils.getTimeDuration(rawConnectTimeout,
TimeUnit.MILLISECONDS);
+ } catch (final Exception e) {
+ logger.warn("Failed to parse value of property '{}' as a valid time period.
Value was '{}'. Ignoring this value and using the default value of '{}'",
+ NiFiProperties.SECURITY_USER_OIDC_CONNECT_TIMEOUT, rawConnectTimeout,
NiFiProperties.DEFAULT_SECURITY_USER_OIDC_CONNECT_TIMEOUT);
+ oidcConnectTimeout = (int) FormatUtils.getTimeDuration(NiFiProperties.DEFAULT_SECURITY_USER_OIDC_CONNECT_TIMEOUT,
TimeUnit.MILLISECONDS);
+ }
+
+ // oidc read timeout
+ final String rawReadTimeout = properties.getOidcReadTimeout();
+ try {
+ oidcReadTimeout = (int) FormatUtils.getTimeDuration(rawReadTimeout, TimeUnit.MILLISECONDS);
+ } catch (final Exception e) {
+ logger.warn("Failed to parse value of property '{}' as a valid time period.
Value was '{}'. Ignoring this value and using the default value of '{}'",
+ NiFiProperties.SECURITY_USER_OIDC_READ_TIMEOUT, rawReadTimeout,
NiFiProperties.DEFAULT_SECURITY_USER_OIDC_READ_TIMEOUT);
+ oidcReadTimeout = (int) FormatUtils.getTimeDuration(NiFiProperties.DEFAULT_SECURITY_USER_OIDC_READ_TIMEOUT,
TimeUnit.MILLISECONDS);
+ }
+
+ // client id
+ final String rawClientId = properties.getOidcClientId();
+ if (StringUtils.isBlank(rawClientId)) {
+ throw new RuntimeException("Client ID is required when configuring an
OIDC Provider.");
+ }
+ clientId = new ClientID(rawClientId);
+
+ // client secret
+ final String rawClientSecret = properties.getOidcClientSecret();
+ if (StringUtils.isBlank(rawClientSecret)) {
+ throw new RuntimeException("Client secret is required when configured
an OIDC Provider.");
+ }
+ clientSecret = new Secret(rawClientSecret);
+
+ try {
+ // retrieve the oidc provider metadata
+ oidcProviderMetadata = retrieveOidcProviderMetadata(properties.getOidcDiscoveryUrl());
+ } catch (IOException | ParseException e) {
+ throw new RuntimeException("Unable to retrieve OpenId Connect Provider
metadata from: " + properties.getOidcDiscoveryUrl(), e);
+ }
+
+ // ensure the oidc provider supports basic or post client auth
+ final List<ClientAuthenticationMethod> clientAuthenticationMethods
= oidcProviderMetadata.getTokenEndpointAuthMethods();
+ if (clientAuthenticationMethods == null
+ || (!clientAuthenticationMethods.contains(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
+ && !clientAuthenticationMethods.contains(ClientAuthenticationMethod.CLIENT_SECRET_POST)))
{
+
+ throw new RuntimeException(String.format("OpenId Connect Provider does
not support %s or %s",
+ ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue(),
+ ClientAuthenticationMethod.CLIENT_SECRET_POST.getValue()));
+ }
+
+ // extract the supported json web signature algorithms
+ final List<JWSAlgorithm> allowedAlgorithms = oidcProviderMetadata.getIDTokenJWSAlgs();
+ if (allowedAlgorithms == null || allowedAlgorithms.isEmpty()) {
+ throw new RuntimeException("The OpenId Connect Provider does not support
any JWS algorithms.");
+ }
+
+ try {
+ // get the preferred json web signature algorithm
+ final String rawPreferredJwsAlgorithm = properties.getOidcPreferredJwsAlgorithm();
+
+ final JWSAlgorithm preferredJwsAlgorithm;
+ if (StringUtils.isBlank(rawPreferredJwsAlgorithm)) {
+ preferredJwsAlgorithm = oidcProviderMetadata.getIDTokenJWSAlgs().get(0);
+ } else {
+ if ("none".equals(rawPreferredJwsAlgorithm)) {
+ preferredJwsAlgorithm = null;
+ } else {
+ preferredJwsAlgorithm = JWSAlgorithm.parse(rawPreferredJwsAlgorithm);
+ }
+ }
+
+ if (preferredJwsAlgorithm == null) {
--- End diff --
- preferred algorithm = none will attempt to validate unsecured/plain tokens
- preferred algorithm is not specified will attempt to use which ever is the first supported
algorithm from the OP metadata
- when the preferred algorithm is HMAC/SHA-*, use the client secret
- which class is deprecated? I don't appear to be using anything deprecated.
- using the constructor you specified, I don't think we can specify our own timeout values
> Add OpenId Connect support for authenticating users
> ---------------------------------------------------
>
> Key: NIFI-4210
> URL: https://issues.apache.org/jira/browse/NIFI-4210
> Project: Apache NiFi
> Issue Type: Improvement
> Components: Core Framework, Core UI
> Reporter: Matt Gilman
> Assignee: Matt Gilman
>
> Add support for authenticating users with the OpenId Connection specification. Evaluate
whether a new extension point is necessary to allow for a given provider to supply custom
code for instance to implement custom token validation.
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)
|