spring-boot saml: configure service provider entityId - spring-boot

Is there a way to configure the entityID of the service provider in the following configuration:
spring:
security:
saml2:
relyingparty:
registration:
myapp:
signing:
credentials:
- private-key-location: "classpath:private.pem"
certificate-location: "classpath:public.pem"
identityprovider:
entity-id: idp
singlesignon:
sign-request: false
url: https://.../auth/realms/saml-demo/protocol/saml
Currently the identity provider is always receiving the following format:
{baseUrl}/saml2/service-provider-metadata/{registrationId}
For example:
http://localhost:8080/saml2/service-provider-metadata/myapp
Can this format be customized when using the yaml config?

Related

Spring boot app access to Azure Keyvault secret

I am trying to set up a Spring boot app to connect to Azure keyvault and fetch secrets.
I have looked across various code samples, but cannot get one to work.
There are no errors related to the keyvault library itself, but the Spring bean does not get initialized with the property fetched from the secret.
I am using Spring boot 2.7.3 and the keyvault starter lib is 4.2.0. This is what I referred to get my property config.
https://microsoft.github.io/spring-cloud-azure/4.2.0/reference/html/appendix.html#_azure_key_vault_secrets_properties
application.yml
------------
spring:
cloud:
azure:
keyvault:
secret:
enabled: true
endpoint: https://uri/
credential:
client-certificate-path: <path to pem file>
client-id: <client-id>
profile:
tenant-id: <tenant-id>
build.gradle
--------------
implementation 'com.azure.spring:spring-cloud-azure-starter-keyvault-secrets:4.2.0'
Spring bean
-------------
#Configuration
#Getter
#Setter
public class AKVProperties {
#Value("${MYAPP-DB-LOGIN-PASSWORD}")
private String dbPassword1;
...
Exception at startup:
----------------------
Error creating bean with name 'AKVProperties': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'MYAPP-DB-LOGIN-PASSWORD' in value "${MYAPP-DB-LOGIN-PASSWORD}"
I think the issue is with application.yaml file. you have to set your config settings under property-sources: .
This is the application.yaml I used where everython is set under the property-sources:
spring:
cloud:
azure:
keyvault:
secret:
property-sources:
- credential:
client-id: <CLIENT ID>
client-secret: <CLIENT SECRET>
endpoint: '<END POINT>'
profile:
tenant-id: <TENANT ID>
Here I have retriving the secret like this
#Value("${secret}")
private String secret;
and then I am just console logging them .
Output:
Keyvault:

Spring boot cloud vault does not load properties anymore after update to version 3.0.3

I'm facing the same problem as bootstrap.yml configuration not processed anymore with Spring Cloud 2020.0.
I updated spring boot cloud to the version 3.0.3. My config is:
spring:
config:
import: vault://
cloud:
vault:
enabled: true
uri: ${uri}
authentication: APPROLE
kv:
enabled: true
backend: secrets
application-name: ${path}
generic:
enabled: false
app-role:
role-id: ${role_id}
secret-id: ${secret_id}
The connection settings seems to be ok because there are some 'permission denied' log entries (path to this vault in invalid)
Vault location [secrets/application/develop] not resolvable: Status
403 Forbidden [secrets/data/application/develop]: 1 error occurred: *
permission denied ; nested exception is
org.springframework.web.client.HttpClientErrorException$Forbidden: 403
Forbidden: [{"errors":["1 error occurred:\n\t* permission
denied\n\n"]}
Any hints what's wrong?
I found the problem. it's not working when application-name is defined at spring.cloud.vault.kv.application-name. It has to be defined as spring.cloud.vault.application-name but according to https://github.com/spring-cloud/spring-cloud-vault/blob/main/docs/src/main/asciidoc/secret-backends.adoc it should also work for spring.cloud.vault.kv.application-name....
spring:
config:
import: vault://
cloud:
vault:
enabled: true
uri: ${uri}
authentication: APPROLE
application-name: ${path}
kv:
enabled: true
backend: secrets
generic:
enabled: false
app-role:
role-id: ${role_id}
secret-id: ${secret_id}

Issuer mismatch : WSO2 IS and Spring Boot but same URI configured

I'm just reproducing the WSO2 IS official tutorial here : https://is.docs.wso2.com/en/5.11.0/develop/spring-boot/
There for in Spring, my OIDC configuration is simply :
provider:
host: https://localhost:9443 #Change the host
spring:
security:
oauth2:
client:
registration:
wso2:
client-name : WSO2 Identity Server
client-id: aXOWlNxT0aKIfKIeH82IfsmLjsYa #Change client-id
client-secret: CVl_vmEYqRuZddBu3ZCYQQwGtYsa # Change client-secret
authorization-grant-type: authorization_code
scope: openid
provider:
wso2:
issuer-uri: ${provider.host}/oauth2/oidcdiscovery
thymeleaf:
cache: false
Nonetheless, I still get this Error :
Caused by: java.lang.IllegalStateException: The Issuer
"https://localhost:9443/oauth2/token" provided in the configuration
metadata did not match the requested issuer
"https://localhost:9443/oauth2/oidcdiscovery" at
org.springframework.util.Assert.state(Assert.java:97)
~[spring-core-5.3.2.jar:5.3.2] at
org.springframework.security.oauth2.client.registration.ClientRegistrations.withProviderConfiguration(ClientRegistrations.java:239)
~[spring-security-oauth2-client-5.4.2.jar:5.4.2] at
org.springframework.security.oauth2.client.registration.ClientRegistrations.lambda$oidc$0(ClientRegistrations.java:158)
~[spring-security-oauth2-client-5.4.2.jar:5.4.2] at
Also, my WSO2 IS is properly configured. Only defaults. As shown in the screenshot below with Identity Provider configuration
What should I do ?
This issue has been already reported [1], and as the solution /token endpoint has been configured for the discovery request [2].

Oauth2 security behind load balander

I'm struggling with authorization problem within my local kubernetes cluster when my application are replicated and listen behind load balancer.
architecture-image
I've created some basic application using spring boot and security oauth2 library. I've also launch keycloak (sso) application. They are listening under domains: hello.org (app) and sso.org (keycloak). I thought to add some load balancing before application, but there is the main problem. How to properly complete the login process if the requests are spread evenly over e.g two pods? The authorization process required few redirects, so first request will go to first one, second to another and process will fail cause they don't have shared information about state.
I'm using authorization code flow.
Here is my libraries responsible for security implementation and basic config.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
server:
port: 8080
logging:
level:
org.springframework.security: DEBUG
org.springframework.security.oauth2: DEBUG
org.springframework.security.jwt: DEBUG
keycloak-client:
server-url: http://sso.org/auth
realm: demo
spring:
security:
oauth2:
client:
registration:
keycloak:
client-id: hello-app
client-secret: b3ed7f13-88cc-4de1-9dc0-59c80b310dfb
client-name: Hello Application
authorization-grant-type: authorization_code
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
scope:
- hello
- openid
- profile
- email
provider:
keycloak:
token-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/token
authorization-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/auth
user-info-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/userinfo
jwk-set-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/certs
user-name-attribute: preferred_username
filter:
order: 100
I found a way to resolve my problem with sticky session implementation on Load Balancer. It's not the best solution, but for my case is just fine.
Here is my Ingress configuration to enable sticky session.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: hello-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "INGRESS"
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
nginx.ingress.kubernetes.io/session-cookie-path: /
spec:
rules:
- host: hello.org
http:
paths:
- path: /
backend:
serviceName: hello-app
servicePort: 8080
For more information visit: https://kubernetes.github.io/ingress-nginx/examples/affinity/cookie/

Zuul -> Eureka Server, Basic Authentication issue

I am able to hit the service, if the flow doesn't contain Basic Authorization.
If i use Basic Authorization, it throws "message": "Full authentication is required to access this resource"
Below are my observations:
In ZuulFilter, run() method, i get value for
request.getHeader("Authorization") --> Basic c29tOnNvbzz==
but once it reaches the Micro Service, i am getting value as 'null',
request.getHeader("Authorization") --> null
Using Spring Boot version : 1.4.0.RELEASE
This is my flow:
------------------
Zuul -> Service Discovery (Eureka Server) -> Service
Kindly help, not sure where the Authorization header is vanishing.
Eureka Server yml file:
-------------------------
server.port:4001
eureka.instance.hostname=localhost
eureka.client.fetch-registry:false
eureka.client.register-with-eureka:false
eureka.client.serviceUrl.defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
eureka.client.healthcheck.enabled=true
Zuul yml file:
-----------------
server:
port: 8765
info:
component: Edge Server
eureka:
instance:
leaseRenewalIntervalInSeconds: 3
metadataMap:
instanceId: ${spring.application.name}:${random.value}
client:
# Default values comes from org.springframework.cloud.netflix.eurek.EurekaClientConfigBean
registryFetchIntervalSeconds: 5
instanceInfoReplicationIntervalSeconds: 5
initialInstanceInfoReplicationIntervalSeconds: 5
endpoints:
restart:
enabled: true
shutdown:
enabled: true
health:
sensitive: false
zuul.sensitive-headers: Cookie,Set-Cookie,Authorization
logging:
level:
ROOT: WARN
se.callista: INFO
# Get info regarding connection to the cofig server and retries if required
org.springframework.cloud.config.client.ConfigServicePropertySourceLocator: INFO
org.springframework.retry.support.RetryTemplate: DEBUG
# Set INFO to see the allocated port
org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer: INFO
---
eureka:
instance:
preferIpAddress: true
client:
serviceUrl:
defaultZone: http://localhost:4001/eureka,http://localhost:4002/eureka
Authorization is by default a sensitive header, this means Zuul will not forward them. If you leave it out of the sensitive headers, Zuul will forward the header.
zuul.sensitiveHeaders: Cookie,Set-Cookie
It should also be camelCase instead of hyphenated.
Extra info: https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#cookies-and-sensitive-headers
This solved my problem, but is this the only solution we have ?
ctx.addZuulRequestHeader("Authorization",request.getHeader("‌​Authorization"))
Your property for zuul.sensitiveHeaders is wrong. It is camel case not hyphenated.
https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#cookies-and-sensitive-headers

Resources