Skip to content

Commit

Permalink
OIDC update to support HTTPS identity provider on plain socket Helidon (
Browse files Browse the repository at this point in the history
helidon-io#4222)

* OIDC update to support HTTPS identity provider on plain socket Helidon
  • Loading branch information
tomas-langer committed May 26, 2022
1 parent 578bb6b commit fc540cf
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 3 deletions.
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 @@ -308,6 +308,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 @@ -332,6 +338,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 @@ -374,6 +381,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 @@ -406,6 +414,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 @@ -536,6 +545,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 @@ -1090,6 +1108,7 @@ public static class Builder implements io.helidon.common.Builder<Builder, OidcCo
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 @@ -1292,6 +1311,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 @@ -1805,6 +1825,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

0 comments on commit fc540cf

Please sign in to comment.