Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.x: Unified constants for configuring outbound id and secret. #7415

Merged
merged 2 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@
import java.util.Set;

import io.helidon.http.Http;
import io.helidon.webserver.testing.junit5.ServerTest;
import io.helidon.security.EndpointConfig;
import io.helidon.security.Security;
import io.helidon.security.providers.httpauth.HttpBasicAuthProvider;
import io.helidon.webclient.http1.Http1Client;
import io.helidon.webclient.http1.Http1ClientResponse;
import io.helidon.webclient.security.WebClientSecurity;
import io.helidon.security.Security;
import io.helidon.security.providers.httpauth.HttpBasicAuthProvider;
import io.helidon.webserver.testing.junit5.ServerTest;

import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -141,8 +142,8 @@ private Http1ClientResponse callProtected(String uri, String username, String pa
// here we call the endpoint
return client.get()
.uri(uri)
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_USER, username)
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_PASSWORD, password)
.property(EndpointConfig.PROPERTY_OUTBOUND_ID, username)
.property(EndpointConfig.PROPERTY_OUTBOUND_SECRET, password)
.request();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
*/
package io.helidon.security.examples.outbound;

import io.helidon.security.EndpointConfig;
import io.helidon.security.SecurityContext;
import io.helidon.security.providers.jwt.JwtProvider;
import io.helidon.webclient.http1.Http1Client;
import io.helidon.webclient.security.WebClientSecurity;
import io.helidon.webserver.WebServer;
Expand Down Expand Up @@ -47,7 +47,7 @@ private void override(ServerRequest req, ServerResponse res) {
.orElseThrow(() -> new RuntimeException("WebServer not found in context"));

String result = client.get("http://localhost:" + server.port("backend") + "/hello")
.property(JwtProvider.EP_PROPERTY_OUTBOUND_USER, "jill")
.property(EndpointConfig.PROPERTY_OUTBOUND_ID, "jill")
.requestEntity(String.class);

res.send("You are: " + context.userName() + ", backend service returned: " + result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
*/
package io.helidon.security.examples.outbound;

import io.helidon.security.EndpointConfig;
import io.helidon.security.SecurityContext;
import io.helidon.security.providers.httpauth.HttpBasicAuthProvider;
import io.helidon.webclient.http1.Http1Client;
import io.helidon.webclient.security.WebClientSecurity;
import io.helidon.webserver.WebServer;
Expand Down Expand Up @@ -48,8 +48,8 @@ private void override(ServerRequest req, ServerResponse res) {
.orElseThrow(() -> new RuntimeException("WebServer not found in context"));

String result = client.get("http://localhost:" + server.port("backend") + "/hello")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_USER, "jill")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_PASSWORD, "anotherPassword")
.property(EndpointConfig.PROPERTY_OUTBOUND_ID, "jill")
.property(EndpointConfig.PROPERTY_OUTBOUND_SECRET, "anotherPassword")
.requestEntity(String.class);

res.send("You are: " + context.userName() + ", backend service returned: " + result + "\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@

import java.net.URI;

import io.helidon.webserver.testing.junit5.ServerTest;
import io.helidon.webserver.testing.junit5.SetUpServer;
import io.helidon.security.EndpointConfig;
import io.helidon.security.Security;
import io.helidon.security.providers.httpauth.HttpBasicAuthProvider;
import io.helidon.webclient.http1.Http1Client;
import io.helidon.webclient.security.WebClientSecurity;
import io.helidon.webserver.WebServer;
import io.helidon.webserver.WebServerConfig;
import io.helidon.security.Security;
import io.helidon.security.providers.httpauth.HttpBasicAuthProvider;
import io.helidon.webserver.testing.junit5.ServerTest;
import io.helidon.webserver.testing.junit5.SetUpServer;

import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -59,8 +60,8 @@ public static void setup(WebServerConfig.Builder server) {
public void testOverrideExample() {
String value = client.get()
.path("/override")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_USER, "jack")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_PASSWORD, "password")
.property(EndpointConfig.PROPERTY_OUTBOUND_ID, "jack")
.property(EndpointConfig.PROPERTY_OUTBOUND_SECRET, "password")
.requestEntity(String.class);

assertThat(value, is("You are: jack, backend service returned: jill\n"));
Expand All @@ -70,8 +71,8 @@ public void testOverrideExample() {
public void testPropagateExample() {
String value = client.get()
.path("/propagate")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_USER, "jack")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_PASSWORD, "password")
.property(EndpointConfig.PROPERTY_OUTBOUND_ID, "jack")
.property(EndpointConfig.PROPERTY_OUTBOUND_SECRET, "password")
.requestEntity(String.class);

assertThat(value, is("You are: jack, backend service returned: jack\n"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@

import java.net.URI;

import io.helidon.webserver.testing.junit5.ServerTest;
import io.helidon.webserver.testing.junit5.SetUpServer;
import io.helidon.security.EndpointConfig;
import io.helidon.security.Security;
import io.helidon.security.providers.httpauth.HttpBasicAuthProvider;
import io.helidon.webclient.http1.Http1Client;
import io.helidon.webclient.http1.Http1ClientResponse;
import io.helidon.webclient.security.WebClientSecurity;
import io.helidon.webserver.WebServer;
import io.helidon.webserver.WebServerConfig;
import io.helidon.security.Security;
import io.helidon.security.providers.httpauth.HttpBasicAuthProvider;
import io.helidon.webserver.testing.junit5.ServerTest;
import io.helidon.webserver.testing.junit5.SetUpServer;

import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -60,8 +61,8 @@ public static void setup(WebServerConfig.Builder server) {
public void testOverrideExample() {
try (Http1ClientResponse response = client.get()
.path("/override")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_USER, "jack")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_PASSWORD, "password")
.property(EndpointConfig.PROPERTY_OUTBOUND_ID, "jack")
.property(EndpointConfig.PROPERTY_OUTBOUND_SECRET, "password")
.request()) {

assertThat(response.status().code(), is(200));
Expand All @@ -75,8 +76,8 @@ public void testOverrideExample() {
public void testPropagateExample() {
try (Http1ClientResponse response = client.get()
.path("/propagate")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_USER, "jack")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_PASSWORD, "password")
.property(EndpointConfig.PROPERTY_OUTBOUND_ID, "jack")
.property(EndpointConfig.PROPERTY_OUTBOUND_SECRET, "password")
.request()) {

assertThat(response.status().code(), is(200));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,21 @@
import java.net.URI;
import java.util.Set;

import io.helidon.webserver.testing.junit5.ServerTest;
import io.helidon.security.Security;
import io.helidon.security.providers.httpauth.HttpBasicAuthProvider;
import io.helidon.webclient.http1.Http1Client;
import io.helidon.webclient.http1.Http1ClientResponse;
import io.helidon.webclient.security.WebClientSecurity;
import io.helidon.webserver.WebServer;
import io.helidon.security.Security;
import io.helidon.security.providers.httpauth.HttpBasicAuthProvider;
import io.helidon.webserver.testing.junit5.ServerTest;

import org.junit.jupiter.api.Test;

import static io.helidon.security.providers.httpauth.HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_PASSWORD;
import static io.helidon.security.providers.httpauth.HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_USER;
import static io.helidon.security.EndpointConfig.PROPERTY_OUTBOUND_ID;
import static io.helidon.security.EndpointConfig.PROPERTY_OUTBOUND_SECRET;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;

@ServerTest
Expand Down Expand Up @@ -66,8 +66,8 @@ public void testService1Rsa() {

private void test(String uri, Set<String> expectedRoles, Set<String> invalidRoles, String service) {
try (Http1ClientResponse response = client.get(uri)
.property(EP_PROPERTY_OUTBOUND_USER, "jack")
.property(EP_PROPERTY_OUTBOUND_PASSWORD, "password")
.property(PROPERTY_OUTBOUND_ID, "jack")
.property(PROPERTY_OUTBOUND_SECRET, "password")
.request()) {

assertThat(response.status().code(), is(200));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,14 @@
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
import org.eclipse.microprofile.jwt.JsonWebToken;

import static io.helidon.security.EndpointConfig.PROPERTY_OUTBOUND_ID;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
* Provider that provides JWT authentication.
*/
public class JwtAuthProvider implements AuthenticationProvider, OutboundSecurityProvider {

/**
* Configure this for outbound requests to override user to use.
*/
public static final String EP_PROPERTY_OUTBOUND_USER = "io.helidon.security.outbound.user";
/**
* Configuration key for expected issuer of incoming tokens. Used for validation of JWT.
*/
Expand Down Expand Up @@ -379,7 +376,7 @@ public OutboundSecurityResponse outboundSecurity(ProviderRequest providerRequest
SecurityEnvironment outboundEnv,
EndpointConfig outboundEndpointConfig) {

Optional<Object> maybeUsername = outboundEndpointConfig.abacAttribute(EP_PROPERTY_OUTBOUND_USER);
Optional<Object> maybeUsername = outboundEndpointConfig.abacAttribute(PROPERTY_OUTBOUND_ID);
return maybeUsername
.map(String::valueOf)
.flatMap(username -> {
Expand Down Expand Up @@ -951,7 +948,8 @@ public Builder authenticate(boolean authenticate) {

/**
* Whether to allow impersonation by explicitly overriding
* username from outbound requests using {@link #EP_PROPERTY_OUTBOUND_USER} property.
* username from outbound requests using {@link io.helidon.security.EndpointConfig#PROPERTY_OUTBOUND_ID}
* property.
* By default this is not allowed and identity can only be propagated.
*
* @param allowImpersonation set to true to allow impersonation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.List;
import java.util.Optional;

import io.helidon.security.EndpointConfig;
import io.helidon.security.Security;
import io.helidon.security.SecurityContext;
import io.helidon.security.providers.httpauth.HttpBasicAuthProvider;
Expand Down Expand Up @@ -66,16 +67,16 @@ void testSecureClientOverride() {
when(requestContext.getConfiguration()).thenReturn(configuration);
when(requestContext.getProperty(ClientSecurity.PROPERTY_CONTEXT)).thenReturn(context);
when(requestContext.getProperty(ClientSecurity.PROPERTY_PROVIDER)).thenReturn("http-basic-auth");
when(requestContext.getProperty(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_USER)).thenReturn(user);
when(requestContext.getProperty(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_PASSWORD)).thenReturn(password);
when(requestContext.getProperty(EndpointConfig.PROPERTY_OUTBOUND_ID)).thenReturn(user);
when(requestContext.getProperty(EndpointConfig.PROPERTY_OUTBOUND_SECRET)).thenReturn(password);
when(requestContext.getUri()).thenReturn(URI.create("http://localhost:7070/test"));
when(requestContext.getStringHeaders()).thenReturn(new MultivaluedHashMap<>());
when(requestContext.getHeaders()).thenReturn(jerseyHeaders);
when(requestContext.getPropertyNames()).thenReturn(List.of(
ClientSecurity.PROPERTY_CONTEXT,
ClientSecurity.PROPERTY_PROVIDER,
HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_USER,
HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_PASSWORD
EndpointConfig.PROPERTY_OUTBOUND_ID,
EndpointConfig.PROPERTY_OUTBOUND_SECRET
));

ClientSecurityFilter csf = new ClientSecurityFilter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,6 @@
* Provides support for username and password authentication, with support for roles list.
*/
public class HttpBasicAuthProvider implements AuthenticationProvider, OutboundSecurityProvider {
/**
* Configure this for outbound requests to override user to use.
*/
public static final String EP_PROPERTY_OUTBOUND_USER = "io.helidon.security.outbound.user";

/**
* Configure this for outbound requests to override password to use.
*/
public static final String EP_PROPERTY_OUTBOUND_PASSWORD = "io.helidon.security.outbound.password";

static final String HEADER_AUTHENTICATION_REQUIRED = "WWW-Authenticate";
static final String HEADER_AUTHENTICATION = "authorization";
static final String BASIC_PREFIX = "basic ";
Expand Down Expand Up @@ -129,7 +119,7 @@ public boolean isOutboundSupported(ProviderRequest providerRequest,
EndpointConfig outboundEp) {

// explicitly overridden username and/or password
if (outboundEp.abacAttributeNames().contains(EP_PROPERTY_OUTBOUND_USER)) {
if (outboundEp.abacAttributeNames().contains(EndpointConfig.PROPERTY_OUTBOUND_ID)) {
return true;
}

Expand All @@ -142,7 +132,7 @@ public OutboundSecurityResponse outboundSecurity(ProviderRequest providerRequest
EndpointConfig outboundEp) {

// explicit username in request properties
Optional<Object> maybeUsername = outboundEp.abacAttribute(EP_PROPERTY_OUTBOUND_USER);
Optional<Object> maybeUsername = outboundEp.abacAttribute(EndpointConfig.PROPERTY_OUTBOUND_ID);
if (maybeUsername.isPresent()) {
String username = maybeUsername.get().toString();
char[] password = passwordFromEndpoint(outboundEp);
Expand Down Expand Up @@ -182,7 +172,7 @@ public OutboundSecurityResponse outboundSecurity(ProviderRequest providerRequest
.flatMap(this::credentialsFromSubject);
}

Optional<char[]> overridePassword = outboundEp.abacAttribute(EP_PROPERTY_OUTBOUND_PASSWORD)
Optional<char[]> overridePassword = outboundEp.abacAttribute(EndpointConfig.PROPERTY_OUTBOUND_SECRET)
.map(String::valueOf)
.map(String::toCharArray);

Expand All @@ -201,7 +191,7 @@ private Optional<BasicPrivateCredentials> credentialsFromSubject(Subject subject
}

private char[] passwordFromEndpoint(EndpointConfig outboundEp) {
return outboundEp.abacAttribute(EP_PROPERTY_OUTBOUND_PASSWORD)
return outboundEp.abacAttribute(EndpointConfig.PROPERTY_OUTBOUND_SECRET)
.map(String::valueOf)
.map(String::toCharArray)
.orElse(HttpBasicOutboundConfig.EMPTY_PASSWORD);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@
public final class JwtProvider implements AuthenticationProvider, OutboundSecurityProvider {
private static final System.Logger LOGGER = System.getLogger(JwtProvider.class.getName());

/**
* Configure this for outbound requests to override user to use.
*/
public static final String EP_PROPERTY_OUTBOUND_USER = "io.helidon.security.outbound.user";

private final boolean optional;
private final boolean authenticate;
private final boolean propagate;
Expand Down Expand Up @@ -270,7 +265,7 @@ public OutboundSecurityResponse outboundSecurity(ProviderRequest providerRequest
SecurityEnvironment outboundEnv,
EndpointConfig outboundEndpointConfig) {

Optional<Object> maybeUsername = outboundEndpointConfig.abacAttribute(EP_PROPERTY_OUTBOUND_USER);
Optional<Object> maybeUsername = outboundEndpointConfig.abacAttribute(EndpointConfig.PROPERTY_OUTBOUND_ID);
return maybeUsername
.map(String::valueOf)
.flatMap(username -> attemptImpersonation(outboundEnv, username))
Expand Down Expand Up @@ -653,7 +648,8 @@ public Builder authenticate(boolean authenticate) {

/**
* Whether to allow impersonation by explicitly overriding
* username from outbound requests using {@link #EP_PROPERTY_OUTBOUND_USER} property.
* username from outbound requests using {@link io.helidon.security.EndpointConfig#PROPERTY_OUTBOUND_ID}
* property.
* By default this is not allowed and identity can only be propagated.
*
* @param allowImpersonation set to true to allow impersonation
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2021 Oracle and/or its affiliates.
* Copyright (c) 2018, 2023 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -47,6 +47,17 @@
* @see SecurityProvider#supportedAttributes
*/
public class EndpointConfig implements AbacSupport {
/**
* Configure this for outbound requests to override id to use (client id, user - depending on use case).
* This is supported for example for HTTP Basic authentication and JWT authentication providers.
*/
public static final String PROPERTY_OUTBOUND_ID = "io.helidon.security.outbound.identity";
/**
* Configure this for outbound requests to override secret to use (client secret, actual password - depending on use case).
* This is supported for example for HTTP Basic authentication provider.
*/
public static final String PROPERTY_OUTBOUND_SECRET = "io.helidon.security.outbound.secret";

private final List<SecurityLevel> securityLevels;
private final AbacSupport attributes;
private final ClassToInstanceStore<Object> customObjects;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
package io.helidon.webclient.tests;

import io.helidon.http.Http;
import io.helidon.security.EndpointConfig;
import io.helidon.webclient.http1.Http1Client;
import io.helidon.webclient.http1.Http1ClientResponse;
import io.helidon.webserver.WebServer;
import io.helidon.security.providers.httpauth.HttpBasicAuthProvider;

import org.junit.jupiter.api.Test;

Expand All @@ -38,8 +38,8 @@ void testContextCheck() {
Http1Client webClient = createNewClient();
try (Http1ClientResponse r = webClient.get()
.path("/contextCheck")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_USER, "jack")
.property(HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_PASSWORD, "password")
.property(EndpointConfig.PROPERTY_OUTBOUND_ID, "jack")
.property(EndpointConfig.PROPERTY_OUTBOUND_SECRET, "password")
.request()) {
assertThat(r.status().code(), is(Http.Status.OK_200.code()));
}
Expand Down
Loading
Loading