Changeset 7267


Ignore:
Timestamp:
01/05/22 22:27:38 (2 years ago)
Author:
Oliver Schonefeld
Message:
  • experimental basic support for FCS authentication
Location:
FCSSimpleEndpoint/trunk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • FCSSimpleEndpoint/trunk/pom.xml

    r7249 r7267  
    3030
    3131        <dependency>
     32          <groupId>org.bouncycastle</groupId>
     33          <artifactId>bcprov-ext-jdk15on</artifactId>
     34          <version>1.70</version>
     35        </dependency>
     36
     37        <dependency>
     38            <groupId>com.auth0</groupId>
     39            <artifactId>java-jwt</artifactId>
     40            <version>3.18.2</version>
     41        </dependency>
     42
     43        <dependency>
    3244            <groupId>javax.servlet</groupId>
    3345            <artifactId>servlet-api</artifactId>
     
    4052            <groupId>eu.clarin.sru</groupId>
    4153            <artifactId>sru-server</artifactId>
    42             <version>1.8.0</version>
     54            <version>1.10.0-SNAPSHOT</version>
    4355        </dependency>
    4456
  • FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/SimpleEndpointSearchEngineBase.java

    r7115 r7267  
    1717package eu.clarin.sru.server.fcs;
    1818
     19import java.io.File;
     20import java.io.InputStream;
    1921import java.net.URI;
    2022import java.util.List;
    2123import java.util.Map;
     24import java.util.Map.Entry;
    2225
    2326import javax.servlet.ServletContext;
     
    3033import org.z3950.zing.cql.CQLNode;
    3134import org.z3950.zing.cql.CQLTermNode;
     35
     36import eu.clarin.sru.server.SRUAuthenticationInfoProvider;
    3237import eu.clarin.sru.server.SRUConfigException;
    3338import eu.clarin.sru.server.SRUConstants;
     
    4146import eu.clarin.sru.server.SRUServer;
    4247import eu.clarin.sru.server.SRUServerConfig;
     48import eu.clarin.sru.server.fcs.utils.AuthenticationProvider;
     49import eu.clarin.sru.server.utils.SRUAuthenticationInfoProviderFactory;
    4350import eu.clarin.sru.server.utils.SRUSearchEngineBase;
    4451
     
    5057 */
    5158public abstract class SimpleEndpointSearchEngineBase extends
    52         SRUSearchEngineBase {
     59        SRUSearchEngineBase implements SRUAuthenticationInfoProviderFactory {
     60    public static final String FCS_AUTHENTICATION_ENABLE_PARAM =
     61            "eu.clarin.sru.server.fcs.authentication.enable";
     62    public static final String FCS_AUTHENTICATION_AUDIENCE_PARAM =
     63            "eu.clarin.sru.server.fcs.authentication.audience";
     64    public static final String FCS_AUTHENTICATION_IGNORE_ISSUEDAT_PARAM =
     65            "eu.clarin.sru.server.fcs.authentication.ignoreIssuedAt";
     66    public static final String FCS_AUTHENTICATION_ACCEPT_ISSUEDAT_PARAM =
     67            "eu.clarin.sru.server.fcs.authentication.acceptIssuedAt";
     68    public static final String FCS_AUTHENTICATION_ACCEPT_EXPIRESAT_PARAM =
     69            "eu.clarin.sru.server.fcs.authentication.acceptExpiresAt";
     70    public static final String FCS_AUTHENTICATION_ACCEPT_NOTBEFORE_PARAM =
     71            "eu.clarin.sru.server.fcs.authentication.acceptNotBefore";
     72    public static final String FCS_AUTHENTICATION_PUBLIC_KEY_PARAM_PREFIX =
     73            "eu.clarin.sru.server.fcs.authentication.key.";
     74    private static final String RESOURCE_URI_PREFIX = "resource:";
    5375    private static final String X_FCS_ENDPOINT_DESCRIPTION =
    5476            "x-fcs-endpoint-description";
     
    108130        doDestroy();
    109131        super.destroy();
     132    }
     133
     134
     135    @Override
     136    public SRUAuthenticationInfoProvider createAuthenticationInfoProvider(
     137            ServletContext context, Map<String, String> params)
     138            throws SRUConfigException {
     139        String enableAuthentication = params.get(FCS_AUTHENTICATION_ENABLE_PARAM);
     140        if (enableAuthentication != null) {
     141            if (parseBoolean(enableAuthentication)) {
     142                logger.debug("enabling authentication");               
     143                AuthenticationProvider.Builder builder =
     144                        AuthenticationProvider.Builder.create();
     145               
     146                String audience = params.get(FCS_AUTHENTICATION_AUDIENCE_PARAM);
     147                if (audience != null) {
     148                    String[] values = audience.split("\\s*,\\s*");
     149                    if (values != null) {
     150                        for (String value : values) {
     151                            logger.debug("adding audience: {}", value);
     152                            builder.withAudience(value);
     153                        }
     154                    } else {
     155                        logger.debug("adding audience: {}", audience);
     156                        builder.withAudience(audience);
     157                    }
     158                }
     159               
     160                boolean ignoreIssuedAt = parseBoolean(
     161                        params.get(FCS_AUTHENTICATION_IGNORE_ISSUEDAT_PARAM));
     162                if (ignoreIssuedAt) {
     163                    logger.debug("will not verify 'iat' claim");
     164                    builder.withIgnoreIssuedAt();
     165                } else {
     166                    long issuedAtLeeway = parseLong(
     167                            params.get(FCS_AUTHENTICATION_ACCEPT_ISSUEDAT_PARAM), -1);
     168                    if (issuedAtLeeway > 0) {
     169                        logger.debug("allowing {} seconds leeway for 'iat' claim", issuedAtLeeway);
     170                        builder.withIssuedAt(issuedAtLeeway);
     171                    }
     172                }
     173                long expiresAtLeeway = parseLong(
     174                        params.get(FCS_AUTHENTICATION_ACCEPT_EXPIRESAT_PARAM), -1);
     175                if (expiresAtLeeway > 0) {
     176                    logger.debug("allowing {} seconds leeway for 'exp' claim", expiresAtLeeway);
     177                    builder.withExpiresAt(expiresAtLeeway);
     178                }
     179               
     180                long notBeforeLeeway = parseLong(
     181                        params.get(FCS_AUTHENTICATION_ACCEPT_NOTBEFORE_PARAM), -1);
     182                if (notBeforeLeeway > 0) {
     183                    logger.debug("allowing {} seconds leeway for 'nbf' claim", expiresAtLeeway);
     184                    builder.withNotBefore(notBeforeLeeway);
     185                }
     186
     187                // load keys
     188                for (Entry<String, String> entry : params.entrySet()) {
     189                    if (entry.getKey().startsWith(FCS_AUTHENTICATION_PUBLIC_KEY_PARAM_PREFIX)) {
     190                        String keyId = entry.getKey().substring(FCS_AUTHENTICATION_PUBLIC_KEY_PARAM_PREFIX.length()).trim();
     191                        if (keyId.isEmpty()) {
     192                            throw new SRUConfigException("init-parameter: '" + entry.getKey() + "' is invalid: keyId is empty!");
     193                        }
     194                        String keyFileName = entry.getValue();
     195                        logger.debug("keyId = {}, keyFile = {}", keyId, keyFileName);
     196                        if (keyFileName.regionMatches(0, RESOURCE_URI_PREFIX, 0, RESOURCE_URI_PREFIX.length())) {
     197                            String path = keyFileName.substring(RESOURCE_URI_PREFIX.length());
     198                            logger.debug("loading key '{}' from resource '{}'", keyId, keyFileName);
     199                            InputStream in = context.getResourceAsStream(path);
     200                            builder.withPublicKey(keyId, in);
     201                        } else {
     202                            logger.debug("loading key '{}' from file '{}'", keyId, keyFileName);
     203                            builder.withPublicKey(keyId, new File(keyFileName));
     204                        }
     205                    }
     206                }
     207                AuthenticationProvider authenticationProvider = builder.build();
     208                if (authenticationProvider.getKeyCount() == 0) {
     209                    logger.warn("No keys configured, all well-formed tokens will be accepted. Make sure, youn know what you are doing!");
     210                }
     211                return authenticationProvider;
     212            } else {
     213                logger.debug("explictly disable authentication");
     214            }
     215        }
     216        return null;
    110217    }
    111218
     
    251358
    252359
     360    private long parseLong(String value, long defaultValue) throws SRUConfigException {
     361        if (value != null) {
     362            try {
     363                return Long.parseLong(value);
     364            } catch (NumberFormatException e) {
     365                throw new SRUConfigException("invalid long value");
     366            }
     367        }
     368        return defaultValue;
     369    }
     370   
     371   
    253372    private void writeEndpointDescription(XMLStreamWriter writer)
    254373            throws XMLStreamException {
Note: See TracChangeset for help on using the changeset viewer.