20 | SAML 2.0 Login with Spring Security
21 | You are successfully logged in as
22 | User Identity Attributes
23 |
24 |
25 |
26 | | Attribute |
27 | Value |
28 |
29 |
30 |
31 |
32 | |
33 | |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/oauth/gateway/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: gateway
4 | cloud:
5 | gateway:
6 | default-filters:
7 | - TokenRelay=
8 | routes:
9 | - id: callme-service
10 | uri: http://localhost:8040
11 | predicates:
12 | - Path=/callme/**
13 | - id: caller-service
14 | uri: http://localhost:8020
15 | predicates:
16 | - Path=/caller/**
17 | security:
18 | oauth2:
19 | resourceserver:
20 | jwt:
21 | jwk-set-uri: http://localhost:8080/realms/demo/protocol/openid-connect/certs
22 | client:
23 | provider:
24 | keycloak:
25 | issuer-uri: http://localhost:8080/realms/demo
26 | registration:
27 | spring-with-test-scope:
28 | provider: keycloak
29 | client-id: spring-with-test-scope
30 | client-secret: IWLSnakHG8aNTWNaWuSj0a11UY4lzxd9
31 | authorization-grant-type: authorization_code
32 | scope: openid
33 | # keycloak-without-test-scope:
34 | # provider: keycloak
35 | # client-id: spring-without-test-scope
36 | # client-secret: f6fc369d-49ce-4132-8282-5b5d413eba23
37 | # authorization-grant-type: authorization_code
38 | # redirect-uri: "{baseUrl}/login/oauth2/code/spring-without-test-scope"
39 |
40 | server.port: 8060
41 |
42 | logging.level:
43 | org.springframework.cloud.gateway: DEBUG
44 | org.springframework.security: DEBUG
45 | org.springframework.web.reactive.function.client: TRACE
--------------------------------------------------------------------------------
/oauth/gateway/src/test/resources/test-realm.json:
--------------------------------------------------------------------------------
1 | {
2 | "realm": "demo",
3 | "enabled": true,
4 | "users": [
5 | {
6 | "username": "keycloak",
7 | "enabled": true,
8 | "credentials": [
9 | {
10 | "type": "password",
11 | "value": "test"
12 | }
13 | ],
14 | "realmRoles": [
15 | "user"
16 | ]
17 | }
18 | ],
19 | "roles": {
20 | "realm": [
21 | {
22 | "name": "user",
23 | "description": "User privileges"
24 | },
25 | {
26 | "name": "admin",
27 | "description": "Administrator privileges"
28 | }
29 | ]
30 | },
31 | "defaultRoles": [
32 | "user"
33 | ],
34 | "clients": [
35 | {
36 | "clientId": "spring-without-test-scope",
37 | "enabled": true,
38 | "clientAuthenticatorType": "client-secret",
39 | "secret": "f6fc369d-49ce-4132-8282-5b5d413eba23",
40 | "publicClient": true,
41 | "redirectUris": [
42 | "*"
43 | ],
44 | "webOrigins": [
45 | "*"
46 | ],
47 | "defaultClientScopes": [
48 | "role_list",
49 | "profile",
50 | "email"
51 | ]
52 | },
53 | {
54 | "clientId": "spring-with-test-scope",
55 | "enabled": true,
56 | "clientAuthenticatorType": "client-secret",
57 | "secret": "c6480137-1526-4c3e-aed3-295aabcb7609",
58 | "publicClient": true,
59 | "redirectUris": [
60 | "*"
61 | ],
62 | "webOrigins": [
63 | "*"
64 | ],
65 | "defaultClientScopes": [
66 | "role_list",
67 | "profile",
68 | "email",
69 | "TEST"
70 | ]
71 | }
72 | ]
73 | }
--------------------------------------------------------------------------------
/ssl/secure-caller/k8s/deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: secure-caller
5 | annotations:
6 | secret.reloader.stakater.com/reload: "secure-caller-cert,secure-callme-cert"
7 | spec:
8 | selector:
9 | matchLabels:
10 | app.kubernetes.io/name: secure-caller
11 | template:
12 | metadata:
13 | labels:
14 | app.kubernetes.io/name: secure-caller
15 | spec:
16 | containers:
17 | - image: piomin/secure-caller
18 | name: secure-caller
19 | ports:
20 | - containerPort: 8443
21 | name: https
22 | env:
23 | - name: PASSWORD
24 | valueFrom:
25 | secretKeyRef:
26 | key: password
27 | name: jks-password-secret
28 | - name: CERT_PATH
29 | value: /opt/secret
30 | - name: CLIENT_CERT_PATH
31 | value: /opt/client-secret
32 | - name: HOST
33 | value: secure-callme
34 | volumeMounts:
35 | - mountPath: /opt/secret
36 | name: cert
37 | - mountPath: /opt/client-secret
38 | name: client-cert
39 | volumes:
40 | - name: cert
41 | secret:
42 | secretName: secure-caller-cert
43 | - name: client-cert
44 | secret:
45 | secretName: secure-callme-cert
46 | ---
47 | apiVersion: v1
48 | kind: Service
49 | metadata:
50 | labels:
51 | app.kubernetes.io/name: secure-caller
52 | name: secure-caller
53 | spec:
54 | ports:
55 | - name: https
56 | port: 8443
57 | targetPort: 8443
58 | selector:
59 | app.kubernetes.io/name: secure-caller
60 | type: ClusterIP
--------------------------------------------------------------------------------
/saml/callme-saml/src/main/java/pl/piomin/samples/security/callme/saml/CallmeSamlApplication.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.samples.security.callme.saml;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
7 | import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver;
8 | import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
9 | import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
10 | import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver;
11 |
12 | @SpringBootApplication
13 | public class CallmeSamlApplication {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(CallmeSamlApplication.class, args);
17 | }
18 |
19 | // @Bean
20 | // Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) {
21 | // RelyingPartyRegistrationResolver registrationResolver =
22 | // new DefaultRelyingPartyRegistrationResolver(registrations);
23 | // OpenSaml4AuthenticationRequestResolver authenticationRequestResolver =
24 | // new OpenSaml4AuthenticationRequestResolver(registrationResolver);
25 | // authenticationRequestResolver.setAuthnRequestCustomizer((context) -> context
26 | // .getAuthnRequest().setForceAuthn(true));
27 | // return authenticationRequestResolver;
28 | // }
29 | }
30 |
--------------------------------------------------------------------------------
/ssl/secure-caller-bundle/k8s/deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: secure-caller-bundle
5 | spec:
6 | selector:
7 | matchLabels:
8 | app.kubernetes.io/name: secure-caller-bundle
9 | template:
10 | metadata:
11 | labels:
12 | app.kubernetes.io/name: secure-caller-bundle
13 | spec:
14 | containers:
15 | - image: piomin/secure-caller-bundle
16 | name: secure-caller-bundle
17 | ports:
18 | - containerPort: 8443
19 | name: https
20 | env:
21 | - name: PASSWORD
22 | valueFrom:
23 | secretKeyRef:
24 | key: password
25 | name: jks-password-secret
26 | - name: CERT_PATH
27 | value: /opt/secret
28 | - name: CLIENT_CERT_PATH
29 | value: /opt/client-secret
30 | - name: HOST
31 | value: secure-callme-bundle
32 | - name: SPRING_PROFILES_ACTIVE
33 | value: prod
34 | volumeMounts:
35 | - mountPath: /opt/secret
36 | name: cert
37 | - mountPath: /opt/client-secret
38 | name: client-cert
39 | volumes:
40 | - name: cert
41 | secret:
42 | secretName: secure-caller-cert
43 | - name: client-cert
44 | secret:
45 | secretName: secure-callme-cert
46 | ---
47 | apiVersion: v1
48 | kind: Service
49 | metadata:
50 | labels:
51 | app.kubernetes.io/name: secure-caller-bundle
52 | name: secure-caller-bundle
53 | spec:
54 | ports:
55 | - name: https
56 | port: 8443
57 | targetPort: 8443
58 | selector:
59 | app.kubernetes.io/name: secure-caller-bundle
60 | type: ClusterIP
--------------------------------------------------------------------------------
/saml/callme-saml/src/main/resources/rp-key.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCrXxU7l9VLkT9Y
3 | 0TrRp0IH1gjNOW45/g4oywN0QGvXv98sm6pnm0zTasqVq5Q1whau7MgfOt8auWzA
4 | aNEvnD4/atY423yWSMLxxxzDlj4q4wfbqU+RZpvkpboEYXh28Up3pn8jkczuYcc0
5 | kRuG3z3cSLQW3NimPcm+sbt+22JRP+e3wWLuc3tQBcEdGbDoIJmtwivvhUWbjKPQ
6 | 6pnfjALDoKC0ZNYGwwr702GBD7Ox9xQ6GmnBpO1CrUzAbCpM4NjgBpbWDTmmg7Hv
7 | xhbw+hxDY9SZCuqLhObO52fILA0Xsu7ok/8Fx/kSLQWyqdSICxnbeXt+ZJqhxRDK
8 | gDrHGxJ7AgMBAAECggEAGYofGPWE1TE9VphAAtTBc3eDckpX0g65v3yZ9C5RpCK1
9 | OOmuGKi9Z1in/mxGt0hIpyMko/rbGxl9SqOUYVsQr9TVPj3/sEoBu5SoBcITW8Lf
10 | /e2arRm0q/vC4DpCgL9vEKvgkMV+3Bv4Wy4xAwWsK3MuW6XoJ8ZXlbLZNYuueFsl
11 | 9WJ0KAjcBmCh9iuRgAAclrPnEYwDxVF5rBcDlwOVFomfsj+hS+l7GE6VDDpKgnEJ
12 | RbyLExBIOmSe74XEvDMXRcIQXX4FCKrp97Rn0JZE8UsWfF/CXBcalZ0W7haAK0Oo
13 | WEBujh4RXD4CrYiEpELB0504FKozuFtQ0LiRM9KiUQKBgQDqD9e1QTA4HBlfZfwp
14 | qcBVT9VfX5gHQr/HdEiC+Fq7MaJPMQDVTUVlC5Da8CSSHXEUC6ELXMT2Jkbmbn7N
15 | rNG5h+UKYpAbY+k4DK0DD2RgXaGlpnsTcZftAgTpb6EnR6t6zfZRas8Xh+Id8lTE
16 | lUBrNtyWyqdedJ4FvxwR4d+hWQKBgQC7bwZWuRwMuxMjcZ3qwDU2sJSokCkTAwhH
17 | 3QV9Jnyh98b0jBWDgHZPG6WlL2ff9J+x1/vMVQIOyaggpfC1xMjq8/iasfcJYODP
18 | G61WiQRG4M3M7v2k1USHMDSmXW7EUk0G6ZuWGy28SWKaEyBz6/4hrA4108mYr39X
19 | rwPCPnvj8wKBgCqg+Ahq9v1BIN3fFS4BXKYtBA96uZWY8pTA+PPhh6TQRV9m7V/r
20 | 0te0Y418byytcArWk14eZ0Dtd7xAI5gSAaBov65EhTp31+H9bQVBqGZkpywkRgYk
21 | iicAVySs0Az3YKPdHx909IK0nNoXaJjlFfZw53wPLKxnUOB7DgGzwacBAoGAJkw+
22 | QFQcfiFvfKuHd+MEPIOCLJsgOWlCNOTdbUAC8VlehrNk5fTGt81PYFw6XlFum/kk
23 | 0xB/liPwPZOKhqmJ4DAvmPRKJNlttgPSvD7M5+qhQoGGxDprgTABYgjvTCAA6yuq
24 | hdZR1woroo3L8MPErn6ofKkkpRUe8PyqyPLZf68CgYB/JfzTPkswE6G8cLCaIHme
25 | EgHe2oE0h+g7hjXfvOqueFqrrZm/TKUqvRkcmzbsIMhMi97ulq9wLSwvuBbiVv6d
26 | 4a0p7GHi43dMmBaQxsxCEhGko56GKWu91kw8Fb5C3ui8zeH2zIQ2JhltVGWdUj1q
27 | XMm2j1gQp+fEUYyjcmivFw==
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/ssl/secure-callme-bundle/src/test/java/pl/piomin/services/callme/SecureCallmeBundleTest.java:
--------------------------------------------------------------------------------
1 | package pl.piomin.services.callme;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.boot.ssl.SslBundles;
6 | import org.springframework.boot.test.context.SpringBootTest;
7 | import org.springframework.boot.test.context.TestConfiguration;
8 | import org.springframework.boot.test.web.client.TestRestTemplate;
9 | import org.springframework.boot.test.web.server.LocalServerPort;
10 | import org.springframework.boot.web.client.RestTemplateBuilder;
11 | import org.springframework.context.annotation.Bean;
12 | import org.springframework.context.annotation.Primary;
13 | import org.springframework.http.client.ClientHttpRequestFactory;
14 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
15 | import org.springframework.web.client.RestTemplate;
16 |
17 | import javax.net.ssl.SSLContext;
18 |
19 | import java.net.http.HttpClient;
20 |
21 | import static org.junit.jupiter.api.Assertions.assertEquals;
22 |
23 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
24 | public class SecureCallmeBundleTest {
25 |
26 | @Autowired
27 | RestTemplate restTemplate;
28 | @LocalServerPort
29 | Integer port;
30 |
31 | @Test
32 | void call() {
33 | String res = restTemplate.getForObject("https://localhost:" + port + "/callme", String.class);
34 | assertEquals("I'm secure-callme-bundle!", res);
35 | }
36 |
37 | @TestConfiguration
38 | public static class TestRestTemplateConfiguration {
39 | @Bean
40 | @Primary
41 | RestTemplate restTemplate(RestTemplateBuilder builder, SslBundles sslBundles) {
42 | return builder.setSslBundle(sslBundles.getBundle("server")).build();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/saml/callme-saml/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |