All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.edc.api.auth.delegated.DelegatedAuthenticationService Maven / Gradle / Ivy

/*
 *  Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
 *
 *  This program and the accompanying materials are made available under the
 *  terms of the Apache License, Version 2.0 which is available at
 *  https://www.apache.org/licenses/LICENSE-2.0
 *
 *  SPDX-License-Identifier: Apache-2.0
 *
 *  Contributors:
 *       Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
 *
 */

package org.eclipse.edc.api.auth.delegated;

import org.eclipse.edc.api.auth.spi.AuthenticationService;
import org.eclipse.edc.keys.spi.PublicKeyResolver;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.token.spi.TokenValidationRulesRegistry;
import org.eclipse.edc.token.spi.TokenValidationService;
import org.eclipse.edc.web.spi.exception.AuthenticationFailedException;

import java.util.List;
import java.util.Map;
import java.util.Optional;

import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION;

public class DelegatedAuthenticationService implements AuthenticationService {

    public static final String MANAGEMENT_API_CONTEXT = "management-api";
    @Deprecated(since = "0.7.1")
    private static final String X_API_KEY = "x-api-key";
    public static final String OLD_API_KEY_WARNING = ("Header '%s' found with the DelegatedAuthenticationService. " +
            "Please migrate to using the '%s' header at your earliest convenience, this compatibility feature will be removed in upcoming releases!").formatted(X_API_KEY, AUTHORIZATION);
    private final PublicKeyResolver publicKeyResolver;
    private final Monitor monitor;
    private final TokenValidationService tokenValidationService;
    private final TokenValidationRulesRegistry rulesRegistry;

    public DelegatedAuthenticationService(PublicKeyResolver publicKeyResolver,
                                          Monitor monitor,
                                          TokenValidationService tokenValidationService,
                                          TokenValidationRulesRegistry rulesRegistry) {
        this.publicKeyResolver = publicKeyResolver;
        this.monitor = monitor;
        this.tokenValidationService = tokenValidationService;
        this.rulesRegistry = rulesRegistry;
    }

    @Override
    public boolean isAuthenticated(Map> headers) {

        if (headers == null) {
            var msg = "Headers were null";
            monitor.warning(msg);
            throw new AuthenticationFailedException(msg);
        }

        var authHeaders = headers.get(AUTHORIZATION);
        if (authHeaders == null || authHeaders.isEmpty()) {
            // fall back to X-API-Key - backwards compatibility
            authHeaders = headers.get(X_API_KEY);
            if (authHeaders != null && !authHeaders.isEmpty()) {
                monitor.warning(OLD_API_KEY_WARNING);
            }
        }

        return Optional.ofNullable(authHeaders)
                .map(this::performTokenValidation)
                .orElseThrow(() -> {
                    var msg = "Header '%s' not present".formatted(AUTHORIZATION);
                    monitor.warning(msg);
                    return new AuthenticationFailedException(msg);
                });

    }

    private boolean performTokenValidation(List authHeaders) {
        if (authHeaders.size() != 1) {
            monitor.warning("Expected exactly 1 Authorization header, found %d".formatted(authHeaders.size()));
            return false;
        }
        var token = authHeaders.get(0);
        if (!token.toLowerCase().startsWith("bearer ")) {
            monitor.warning("Authorization header must start with 'Bearer '");
            return false;
        }
        token = token.substring(6).trim(); // "bearer" has 7 characters, it could be upper case, lower case or capitalized

        var rules = rulesRegistry.getRules(MANAGEMENT_API_CONTEXT);
        return tokenValidationService.validate(token, publicKeyResolver, rules).succeeded();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy