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

OIDC update to support HTTPS identity provider - 2.x backport #4270

Merged
merged 1 commit into from
May 26, 2022
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 @@ -452,6 +452,9 @@ private CompletionStage<AtxResult> processAuthentication(ServerResponse res,
atnTracing.findParent().orElse(null));

clientBuilder.explicitProvider(explicitAuthenticator.orElse(null)).submit().thenAccept(response -> {
// copy headers to be returned with the current response
response.responseHeaders().forEach(res.headers()::put);

switch (response.status()) {
case SUCCESS:
//everything is fine, we can continue with processing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,12 @@
* <td>&nbsp;</td>
* <td>Cross-origin resource sharing settings. See {@link io.helidon.webserver.cors.CrossOriginConfig}.</td>
* </tr>
* <tr>
* <td>{@code force-https-redirects}</td>
* <td>&nbsp;</td>
* <td>Force https for redirects to identity provider.
* This is helpful if you have a frontend SSL or cloud load balancer in front and Helidon is serving plain http.</td>
* </tr>
* </table>
*/
public final class OidcConfig {
Expand All @@ -333,6 +339,7 @@ public final class OidcConfig {
static final String DEFAULT_ATTEMPT_PARAM = "h_ra";
static final int DEFAULT_MAX_REDIRECTS = 5;
static final int DEFAULT_TIMEOUT_SECONDS = 30;
static final boolean DEFAULT_FORCE_HTTPS_REDIRECTS = false;

private static final Logger LOGGER = Logger.getLogger(OidcConfig.class.getName());
private static final JsonReaderFactory JSON = Json.createReaderFactory(Collections.emptyMap());
Expand Down Expand Up @@ -375,6 +382,7 @@ public final class OidcConfig {
private final URI postLogoutUri;
private final URI logoutEndpointUri;
private final CrossOriginConfig crossOriginConfig;
private final boolean forceHttpsRedirects;

private OidcConfig(Builder builder) {
this.clientId = builder.clientId;
Expand Down Expand Up @@ -407,6 +415,7 @@ private OidcConfig(Builder builder) {
this.generalClient = builder.generalClient;
this.tokenEndpointAuthentication = builder.tokenEndpointAuthentication;
this.clientTimeout = builder.clientTimeout;
this.forceHttpsRedirects = builder.forceHttpsRedirects;

if (tokenEndpointAuthentication == ClientAuthentication.CLIENT_SECRET_POST) {
// we should only store this if required
Expand Down Expand Up @@ -537,6 +546,15 @@ public String redirectUri() {
return redirectUri;
}

/**
* Whether to force https when redirecting to identity provider.
*
* @return {@code true} to force use of https
*/
public boolean forceHttpsRedirects() {
return forceHttpsRedirects;
}

/**
* Whether logout is enabled.
*
Expand Down Expand Up @@ -1091,6 +1109,7 @@ public static class Builder implements io.helidon.common.Builder<OidcConfig> {
private Duration clientTimeout = Duration.ofSeconds(DEFAULT_TIMEOUT_SECONDS);
private URI postLogoutUri;
private CrossOriginConfig crossOriginConfig;
private boolean forceHttpsRedirects = DEFAULT_FORCE_HTTPS_REDIRECTS;

@Override
public OidcConfig build() {
Expand Down Expand Up @@ -1293,6 +1312,7 @@ public Builder config(Config config) {
config.get("redirect").asBoolean().ifPresent(this::redirect);
config.get("redirect-attempt-param").asString().ifPresent(this::redirectAttemptParam);
config.get("max-redirects").asInt().ifPresent(this::maxRedirects);
config.get("force-https-redirects").asBoolean().ifPresent(this::forceHttpsRedirects);

// type of the identity server
// now uses hardcoded switch - should change to service loader eventually
Expand Down Expand Up @@ -1806,6 +1826,19 @@ public Builder useCookie(Boolean useCookie) {
return this;
}

/**
* Force HTTPS for redirects to identity provider.
* Defaults to {@code false}.
*
* @param forceHttpsRedirects flag to redirect with https
* @return updated builder instance
*/
@ConfiguredOption("false")
public Builder forceHttpsRedirects(boolean forceHttpsRedirects) {
this.forceHttpsRedirects = forceHttpsRedirects;
return this;
}

/**
* Name of a query parameter that contains the JWT token when parameter is used.
*
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, 2022 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 @@ -386,7 +386,8 @@ private String redirectUri(SecurityEnvironment env) {
for (Map.Entry<String, List<String>> entry : env.headers().entrySet()) {
if (entry.getKey().equalsIgnoreCase("host") && !entry.getValue().isEmpty()) {
String firstHost = entry.getValue().get(0);
return oidcConfig.redirectUriWithHost(env.transport() + "://" + firstHost);
return oidcConfig.redirectUriWithHost(oidcConfig.forceHttpsRedirects() ? "https" : env.transport()
+ "://" + firstHost);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ private Object postLogoutUri(ServerRequest req) {
path = path.startsWith("/") ? path : "/" + path;
Optional<String> host = req.headers().first("host");
if (host.isPresent()) {
String scheme = req.isSecure() ? "https" : "http";
String scheme = oidcConfig.forceHttpsRedirects() || req.isSecure() ? "https" : "http";
return scheme + "://" + host.get() + path;
} else {
LOGGER.warning("Request without Host header received, yet post logout URI does not define a host");
Expand Down