Skip to content

Commit

Permalink
WiP
Browse files Browse the repository at this point in the history
  • Loading branch information
ch4mpy committed Jun 14, 2024
1 parent 1ee9704 commit 4037708
Show file tree
Hide file tree
Showing 57 changed files with 1,950 additions and 1,423 deletions.
12 changes: 12 additions & 0 deletions angular-ui.app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { provideHttpClient } from '@angular/common/http';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes), provideHttpClient()],
};

export const reverseProxyUri = 'http://LOCALHOST_NAME:7080';
export const baseUri = `${reverseProxyUri}/angular-ui/`;
6 changes: 3 additions & 3 deletions api/bff/src/main/java/com/c4soft/quiz/BffApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@SpringBootApplication
public class BffApplication {

public static void main(String[] args) {
SpringApplication.run(BffApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(BffApplication.class, args);
}
}
47 changes: 24 additions & 23 deletions api/bff/src/main/java/com/c4soft/quiz/BffController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@

import java.net.URISyntaxException;
import java.util.List;

import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.c4_soft.springaddons.security.oidc.starter.properties.SpringAddonsOidcProperties;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotEmpty;
Expand All @@ -21,24 +18,28 @@
@RestController
@Tag(name = "BFF")
public class BffController {
private final List<LoginOptionDto> loginOptions;

public BffController(
OAuth2ClientProperties clientProps,
SpringAddonsOidcProperties addonsProperties,
ReactiveClientRegistrationRepository clientRegistrationRepository) {
this.loginOptions = clientProps.getRegistration().entrySet().stream().filter(e -> "authorization_code".equals(e.getValue().getAuthorizationGrantType()))
.map(e -> new LoginOptionDto(e.getValue().getProvider(), "%s/oauth2/authorization/%s".formatted(addonsProperties.getClient().getClientUri(), e.getKey())))
.toList();
}

@GetMapping(path = "/login-options", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(operationId = "getLoginOptions")
public Mono<List<LoginOptionDto>> getLoginOptions(Authentication auth) throws URISyntaxException {
final boolean isAuthenticated = auth instanceof OAuth2AuthenticationToken;
return Mono.just(isAuthenticated ? List.of() : this.loginOptions);
}

public static record LoginOptionDto(@NotEmpty String label, @NotEmpty String loginUri) {
}
private final List<LoginOptionDto> loginOptions;

public BffController(OAuth2ClientProperties clientProps,
SpringAddonsOidcProperties addonsProperties,
ReactiveClientRegistrationRepository clientRegistrationRepository) {
this.loginOptions =
clientProps.getRegistration().entrySet().stream()
.filter(e -> "authorization_code".equals(e.getValue().getAuthorizationGrantType()))
.map(
e -> new LoginOptionDto(e.getValue().getProvider(),
"%s/oauth2/authorization/%s"
.formatted(addonsProperties.getClient().getClientUri(), e.getKey())))
.toList();
}

@GetMapping(path = "/login-options", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(operationId = "getLoginOptions")
public Mono<List<LoginOptionDto>> getLoginOptions(Authentication auth) throws URISyntaxException {
final boolean isAuthenticated = auth instanceof OAuth2AuthenticationToken;
return Mono.just(isAuthenticated ? List.of() : this.loginOptions);
}

public static record LoginOptionDto(@NotEmpty String label, @NotEmpty String loginUri) {
}
}
47 changes: 9 additions & 38 deletions api/bff/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
scheme: http
keycloak-host: https://oidc.c4-soft.com/auth
keycloak-host: http://localhost/auth
keycloak-realm: quiz
oauth2-issuer: ${keycloak-host}/realms/${keycloak-realm}
oauth2-client-id: quiz-bff
oauth2-client-secret: change-me
oauth2-client-secret: secret

gateway-uri: ${scheme}://localhost:${server.port}
quiz-api-uri: ${scheme}://localhost:7084
ui-host: https://localhost:4200

server:
port: 8080
shutdown: graceful
port: 7080
ssl:
enabled: false

Expand All @@ -35,29 +33,12 @@ spring:
client-id: ${oauth2-client-id}
client-secret: ${oauth2-client-secret}
authorization-grant-type: authorization_code
scope:
- openid
- profile
- email
- offline_access
scope: openid profile email offline_access
cloud:
gateway:
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin Access-Control-Request-Method Access-Control-Request-Headers
routes:
# Redirection from / to /ui/
- id: home
uri: ${gateway-uri}
predicates:
- Path=/
filters:
- RedirectTo=301,${gateway-uri}/ui/
# Serve the Angular app through the gateway
- id: ui
uri: ${ui-host}
predicates:
- Path=/ui/**
# Access the quiz API with BFF pattern
- id: quiz-bff
uri: ${quiz-api-uri}
predicates:
Expand All @@ -66,19 +47,6 @@ spring:
- TokenRelay=
- SaveSession
- StripPrefix=2
# Access the quiz API with OAuth2 clients like Postman
- id: quiz-resource-server
uri: ${quiz-api-uri}
predicates:
- Path=/resource-server/v1/**
filters:
- SaveSession
- StripPrefix=2
# Cert-manager http01 challenge for SSL certificates on K8s
- id: letsencrypt
uri: https://cert-manager-webhook
predicates:
- Path=/.well-known/acme-challenge/**

com:
c4-soft:
Expand All @@ -95,24 +63,27 @@ com:
security-matchers:
- /login/**
- /oauth2/**
- /logout
- /logout/**
- /bff/**
permit-all:
- /login/**
- /oauth2/**
- /logout/connect/back-channel/quiz-bff
- /bff/**
csrf: cookie-accessible-from-js
post-login-redirect-path: /ui/
post-logout-redirect-path: /ui/
oauth2-redirections:
rp-initiated-logout: ACCEPTED
pkce-forced: true
back-channel-logout:
enabled: true
internal-logout-uri: ${scheme}://localhost:${serve.port}/logout
# OAuth2 resource server configuration
resourceserver:
permit-all:
- /login-options
- /ui/**
- /resource-server/**
- /v3/api-docs/**
- /actuator/health/readiness
- /actuator/health/liveness
Expand Down
37 changes: 36 additions & 1 deletion api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<properties>
<java.version>22</java.version>
<spring-cloud-dependencies.version>2023.0.1</spring-cloud-dependencies.version>
<com.c4-soft.springaddons.version>7.8.0</com.c4-soft.springaddons.version>
<com.c4-soft.springaddons.version>7.8.2</com.c4-soft.springaddons.version>
<lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
<org.mapstruct.version>1.6.0.Beta2</org.mapstruct.version>
<openapi-generator-maven-plugin.version>7.6.0</openapi-generator-maven-plugin.version>
Expand Down Expand Up @@ -99,6 +99,11 @@
<artifactId>spring-addons-starter-oidc-test</artifactId>
<version>${com.c4-soft.springaddons.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-starter-rest</artifactId>
<version>${com.c4-soft.springaddons.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-starter-openapi</artifactId>
Expand Down Expand Up @@ -175,6 +180,36 @@
<skip>false</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>${openapi-generator-maven-plugin.version}</version>
<configuration>
<generatorName>spring</generatorName>
<cleanupOutput>false</cleanupOutput>
<skipIfSpecIsUnchanged>true</skipIfSpecIsUnchanged>
<generateApiTests>false</generateApiTests>
<generateModelDocumentation>false</generateModelDocumentation>
<generateModelTests>false</generateModelTests>
<generateSupportingFiles>false</generateSupportingFiles>
<configOptions>
<documentationProvider>none</documentationProvider>
<annotationLibrary>none</annotationLibrary>
<ensureUniqueParams>true</ensureUniqueParams>
<generateBuilders>false</generateBuilders>
<interfaceOnly>true</interfaceOnly>
<library>spring-http-interface</library>
<openApiNullable>false</openApiNullable>
<serializableModel>true</serializableModel>
<skipDefaultInterface>true</skipDefaultInterface>
<useJakartaEe>true</useJakartaEe>
<useOptional>true</useOptional>
</configOptions>
<environmentVariables>
<enablePostProcessFile>true</enablePostProcessFile>
</environmentVariables>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
Expand Down
55 changes: 55 additions & 0 deletions api/quiz-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>jakarta.data</groupId>
<artifactId>jakarta.data-api</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
Expand Down Expand Up @@ -51,6 +56,12 @@
<artifactId>spring-addons-starter-oidc</artifactId>
</dependency>

<!-- REST -->
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-starter-rest</artifactId>
</dependency>

<!-- Observability -->
<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down Expand Up @@ -122,6 +133,50 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<skipValidateSpec>true</skipValidateSpec>
<inputSpec>
${project.basedir}/../keycloak-admin-api.openapi.json</inputSpec>
<apiPackage>org.keycloak.admin.api</apiPackage>
<modelPackage>org.keycloak.admin.model</modelPackage>
<!-- prevent a name colllision between the
deprecated authTime (Integer) and the new auth_time
(Long) in IDToken -->
<nameMappings>auth_time=authTimeLong</nameMappings>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.spotify.fmt</groupId>
<artifactId>fmt-maven-plugin</artifactId>
<version>2.23</version>
<configuration>
<sourceDirectory>target/generated-sources</sourceDirectory>
<verbose>true</verbose>
<filesNamePattern>.*\.java</filesNamePattern>
<skip>false</skip>
<skipSourceDirectory>false</skipSourceDirectory>
<skipTestSourceDirectory>true</skipTestSourceDirectory>
<skipSortingImports>false</skipSortingImports>
<style>google</style>
</configuration>
<executions>
<execution>
<goals>
<goal>format</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Expand Down
Loading

0 comments on commit 4037708

Please sign in to comment.