Skip to content

Commit

Permalink
Resolve baseUrl in redirect URI with external URL
Browse files Browse the repository at this point in the history
Signed-off-by: JohnNiang <[email protected]>
  • Loading branch information
JohnNiang committed Oct 30, 2024
1 parent 6076665 commit 64bc9d4
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 7 deletions.
9 changes: 7 additions & 2 deletions src/main/java/run/halo/oauth/Oauth2LoginConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.ExternalUrlSupplier;
import run.halo.app.security.LoginHandlerEnhancer;

/**
Expand All @@ -38,12 +39,16 @@ public class Oauth2LoginConfiguration {

private final LoginHandlerEnhancer loginHandlerEnhancer;

private final ExternalUrlSupplier externalUrlSupplier;

private ServerRequestCache requestCache = new WebSessionServerRequestCache();

public Oauth2LoginConfiguration(ReactiveExtensionClient extensionClient,
LoginHandlerEnhancer loginHandlerEnhancer) {
LoginHandlerEnhancer loginHandlerEnhancer,
ExternalUrlSupplier externalUrlSupplier) {
this.extensionClient = extensionClient;
this.loginHandlerEnhancer = loginHandlerEnhancer;
this.externalUrlSupplier = externalUrlSupplier;

Initializer initializer = new Initializer();
this.authenticationMatcher = initializer.getAuthenticationMatcher();
Expand All @@ -69,7 +74,7 @@ ServerWebExchangeMatcher createAttemptAuthenticationRequestMatcher() {
}

ReactiveClientRegistrationRepository getClientRegistrationRepository() {
return new OauthClientRegistrationRepository(extensionClient);
return new OauthClientRegistrationRepository(extensionClient, externalUrlSupplier);
}

ServerOAuth2AuthorizedClientRepository getAuthorizedClientRepository() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;

import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -18,10 +19,12 @@
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.util.Assert;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.AuthProvider;
import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.ExternalUrlSupplier;
import run.halo.app.infra.SystemSetting;
import run.halo.app.infra.utils.JsonUtils;

Expand All @@ -36,6 +39,7 @@
public class OauthClientRegistrationRepository implements ReactiveClientRegistrationRepository {
static final String DEFAULT_REDIRECT_URL = "{baseUrl}/{action}/oauth2/code/{registrationId}";
private final ReactiveExtensionClient client;
private final ExternalUrlSupplier externalUrlSupplier;

@Override
public Mono<ClientRegistration> findByRegistrationId(String registrationId) {
Expand Down Expand Up @@ -133,6 +137,15 @@ ClientRegistration.Builder clientRegistrationBuilder(Oauth2ClientRegistration re
"The clientRegistration in AuthProvider must not be null");
}
Oauth2ClientRegistration.Oauth2ClientRegistrationSpec spec = registration.getSpec();
var redirectUri = defaultIfNull(spec.getRedirectUri(), DEFAULT_REDIRECT_URL);
var externalUrl = externalUrlSupplier.getRaw();
if (externalUrl != null) {
// rewrite redirect URI if external Url is configured.
redirectUri = UriComponentsBuilder.fromUriString(redirectUri)
.uriVariables(Map.of("baseUrl", StringUtils.removeEnd(externalUrl.toString(), "/")))
.build()
.toString();
}
return ClientRegistration.withRegistrationId(registration.getMetadata().getName())
.clientName(spec.getClientName())
.clientAuthenticationMethod(
Expand All @@ -144,7 +157,7 @@ ClientRegistration.Builder clientRegistrationBuilder(Oauth2ClientRegistration re
.authorizationUri(spec.getAuthorizationUri())
.issuerUri(spec.getIssuerUri())
.jwkSetUri(spec.getJwkSetUri())
.redirectUri(defaultIfNull(spec.getRedirectUri(), DEFAULT_REDIRECT_URL))
.redirectUri(redirectUri)
.scope(spec.getScopes())
.tokenUri(spec.getTokenUri())
.userInfoAuthenticationMethod(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import org.junit.jupiter.api.Test;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.ExternalUrlSupplier;
import run.halo.app.security.LoginHandlerEnhancer;

/**
Expand All @@ -19,8 +20,9 @@ class Oauth2LoginConfigurationTest {
void constructor() {
ReactiveExtensionClient extensionClient = mock(ReactiveExtensionClient.class);
var loginHandlerEnhancer = mock(LoginHandlerEnhancer.class);
var externalUrlSupplier = mock(ExternalUrlSupplier.class);
Oauth2LoginConfiguration oauth2LoginConfiguration =
new Oauth2LoginConfiguration(extensionClient, loginHandlerEnhancer);
new Oauth2LoginConfiguration(extensionClient, loginHandlerEnhancer, externalUrlSupplier);
assertNotNull(oauth2LoginConfiguration);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.authentication.ProviderNotFoundException;
import org.springframework.security.config.oauth2.client.CommonOAuth2Provider;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import run.halo.app.core.extension.AuthProvider;
import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.Metadata;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.ExternalUrlSupplier;
import run.halo.app.infra.SystemSetting;

/**
Expand All @@ -32,11 +34,14 @@ class OauthClientRegistrationRepositoryTest {
@Mock
private ReactiveExtensionClient client;

@Mock
ExternalUrlSupplier externalUrlSupplier;

@InjectMocks
private OauthClientRegistrationRepository repository;

@Test
void findByRegistrationId_withValidId_returnsClientRegistration() {
void findByRegistrationId_withValidId_returnsClientRegistration() throws MalformedURLException {
AuthProvider authProvider = new AuthProvider();
authProvider.setMetadata(new Metadata());
authProvider.getMetadata().setName("github");
Expand Down Expand Up @@ -79,6 +84,20 @@ void findByRegistrationId_withValidId_returnsClientRegistration() {
assertThat(clientRegistration.getRegistrationId()).isEqualTo("github");
assertThat(clientRegistration.getClientId()).isEqualTo("my-client-id");
assertThat(clientRegistration.getClientSecret()).isEqualTo("my-client-secret");
assertThat(clientRegistration.getRedirectUri()).isEqualTo(
"{baseUrl}/{action}/oauth2/code/{registrationId}"
);
})
.expectComplete()
.verify();

when(externalUrlSupplier.getRaw()).thenReturn(new URL("https://www.halo.run/"));

StepVerifier.create(repository.findByRegistrationId("github"))
.assertNext(clientRegistration -> {
assertThat(clientRegistration.getRedirectUri()).isEqualTo(
"https://www.halo.run/{action}/oauth2/code/{registrationId}"
);
})
.expectComplete()
.verify();
Expand Down

0 comments on commit 64bc9d4

Please sign in to comment.