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

com.dnastack.audit.client.AuthHttpClient Maven / Gradle / Ivy

package com.dnastack.audit.client;

import brave.Tracing;
import com.dnastack.audit.ObjectMapperFactory;
import com.dnastack.audit.exception.InvalidTokenResponseException;
import com.dnastack.audit.model.AuditEventLoggerConfig;
import com.dnastack.audit.model.TokenResponse;
import com.dnastack.auth.PermissionChecker;
import com.dnastack.auth.PermissionCheckerFactory;
import com.dnastack.auth.exception.HttpRequestFailedException;
import com.dnastack.auth.keyresolver.CachingIssuerPubKeyJwksResolver;
import com.dnastack.auth.model.IssuerInfo;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.lang.String.format;

public class AuthHttpClient {

    private final HttpClient httpClient;
    private final ObjectMapper objectMapper;
    private final AuditEventLoggerConfig.OAuthClient oAuthClientConfig;
    private final PermissionChecker permissionChecker;

    public AuthHttpClient(AuditEventLoggerConfig.OAuthClient oAuthClientConfig, Tracing tracing) {
        this.httpClient = HttpClient.newHttpClient();
        this.objectMapper = ObjectMapperFactory.create();
        this.oAuthClientConfig = oAuthClientConfig;
        final List allowedIssuers = oAuthClientConfig.getTokenIssuersUris().stream()
            .distinct()
            .map(issuerUri -> IssuerInfo.IssuerInfoBuilder.builder()
                .issuerUri(issuerUri)
                .allowedAudiences(List.of(oAuthClientConfig.getAudience()))
                .publicKeyResolver(new CachingIssuerPubKeyJwksResolver(issuerUri))
                .build()).collect(Collectors.toList());
        String policyEvaluationRequester = oAuthClientConfig.getPolicyEvaluationRequester();
        String policyEvaluationUri = oAuthClientConfig.getPolicyEvaluationUri();
        this.permissionChecker = PermissionCheckerFactory.create(allowedIssuers, policyEvaluationRequester, policyEvaluationUri, tracing);
    }

    public TokenResponse getTokenResponse() {
        final String credentials = format("%s:%s", oAuthClientConfig.getClientId(), oAuthClientConfig.getClientSecret());
        final String authHeader = format("Basic %s", Base64.getEncoder().encodeToString(credentials.getBytes()));
        final URI uri = URI.create(format("%s?grant_type=client_credentials&resource=%s&scope=%s",
            oAuthClientConfig.getTokenUri(),
            oAuthClientConfig.getResource(),
            oAuthClientConfig.getScopes())
        );

        final HttpRequest request = HttpRequest.newBuilder()
            .uri(uri)
            .header("Authorization", authHeader)
            .POST(HttpRequest.BodyPublishers.noBody())
            .build();

        return getAndValidateResponse(request);
    }

    private TokenResponse getAndValidateResponse(HttpRequest request) {
        final Map response = sendAndReceive(request, Map.class);
        if (response != null && response.containsKey("access_token")) {
            final TokenResponse tokenResponse = objectMapper.convertValue(response, TokenResponse.class);
            permissionChecker.checkPermissions(tokenResponse.getAccessToken(),
                Arrays.asList(oAuthClientConfig.getScopes().split(" ")),
                Map.of(oAuthClientConfig.getResource(), oAuthClientConfig.getActions())
            );
            return tokenResponse;
        } else {
            throw new InvalidTokenResponseException(format("Expected token response instead got response %s", response));
        }
    }

    protected  T sendAndReceive(HttpRequest request, Class responseType) {
        try {
            final HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            return objectMapper.readValue(response.body(), responseType);
        } catch (IOException | InterruptedException ex) {
            throw new HttpRequestFailedException(format("Failed request %s %s", request.method(), request.uri()), ex);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy