I'm writing my first question, please be patient if anything is missing. Any Feedback is welcome.
We have an issue with the generated oauth2RedirectUrl after migrating from a Windows 2012 R2 to a Windows 2016. The server is no longer containing the alias name but the technical server name.
We are using Spring Boot 2.6.0 including spring-boot-starter-oauth2-resource-server and springdoc-openapi-ui 1.5.12.
Spring Boot is set up as a resource server with JWT authorization with Azure OAuth2.
We deploy a FAT Jar on windows machines and recently changed to a new server.
Each machine is has a DNS entry with a technical name and a human readable alias.
Lets say
human-readable-name1 for the old machine
human-readable-name2 for the new machine
We deployed the exact same software on both machines. We access the sawagger ui
with
https://human-readable-name1.domain:port/swagger-ui.html
and
https://human-readable-name2.domain:port/swagger-ui.html
The response from both machines include the generated api-docs which are looking fine.
Containing on both machines like
"servers": [
{
"url": "https://human-readable-name.domain:port",
"description": "Generated server url"
}
]
But the swagger-config change
OLD
{
"configUrl": "/v3/api-docs/swagger-config",
"oauth2RedirectUrl": "https://human-readable-name1:port/swagger-ui/oauth2-redirect.html",
"url": "/v3/api-docs",
"validatorUrl": ""
}
NEW
{
"configUrl": "/v3/api-docs/swagger-config",
"oauth2RedirectUrl": "https://technicalname:port/swagger-ui/oauth2-redirect.html",
"url": "/v3/api-docs",
"validatorUrl": ""
}
This breaks the log in as the token is no longer reaching the swagger ui client.
Any suggestions where I even can start looking for the reason?
Swagger config:
#Configuration
class OpenApiConfig {
#Value("${springdoc.oAuthFlow.authorizationUrl}")
private String authorizationUrl;
#Value("${springdoc.oAuthFlow.tokenUrl}")
private String tokenUrl;
#Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.components(new Components()
.addSecuritySchemes("security_auth",
new SecurityScheme()
.type(SecurityScheme.Type.OAUTH2)
.flows(new OAuthFlows()
.authorizationCode(new OAuthFlow()
.authorizationUrl(authorizationUrl)
.tokenUrl(tokenUrl)
.scopes(new Scopes()
.addString("xxx", "xxx")
)
)
)
)
)
.addSecurityItem(new SecurityRequirement().addList("security_auth"))
;
}
}
Spring Boot yaml
spring.security.oauth2.resourceserver.jwt:
jwk-set-uri: https://login.microsoftonline.com/common/discovery/v2.0/keys
issuer-uri: https://login.microsoftonline.com/xxx/v2.0
springdoc:
swagger-ui:
oauth:
clientId: 'xxx'
use-pkce-with-authorization-code-grant: true
oAuthFlow:
authorizationUrl: https://login.microsoftonline.com/xxx/oauth2/v2.0/authorize
tokenUrl: https://login.microsoftonline.com/xxx/oauth2/v2.0/token
Related
I'm developing an SpringBoot REST project which runs perfectly. I'm trying to implement the OpenApi-ui in the project. It's working fine by default but I'd like to use my own yaml/json information file instead the default info.
I have been following the F.A.Q SpringDoc documentation , but nothing is working for me. It's throwing FAILED TO LOAD API DEFINITION : Fetch error undefined /open-api.yaml in the UI. Am I missing something in my configuration?
Thanks in advance.
Implementation
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.5.9'
App config (route yaml = src/main/resources)
springdoc:api-docs:enabled: false
swagger-ui:url: /open-api.yaml
Configuration
#Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.components(new Components().addSecuritySchemes("basicScheme",
new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic")))
.info(new Info().title("MyApp").version("1.0")
.license(new License().name("Apache 2.0").url("http://springdoc.org")));
}
#Bean
public SpringDocConfiguration springDocConfiguration(){
return new SpringDocConfiguration();
}
#Bean
public SpringDocConfigProperties springDocConfigProperties() {
return new SpringDocConfigProperties();
}
Yaml file
openapi: 3.0.3
info:
title: MyApp
description: MyApp Description
version: 1.0.0
servers:
- url: http://localhost:8080
description: Local server
{...more}
Access URL to OpenApi UI
http://localhost:8080/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config
OpenApi UI Image
Just if someone is looking for something similar, we finally created a new class, extending SwaggerIndexPageTransformer and implementing by SwaggerIndexTransformer , which led us to use #override method to change the url.
You can follow > https://github.com/springdoc/springdoc-openapi/issues/763
i'a trying to deploy my jar spring boot application on windows but get error : [Krb5LoginModule] authentication failed
KrbException: Cannot locate default realm
In my localhost, everything is OK with the authentication but whene i deploy the jar in the production server i got the error even if both windows are in the same campany doamin.
the system administrator told me that for other application, the authentication is based on Kerberos and iis so the ticket exchange for authentication is very easy.
Here's my security config :
#Bean
public KerberosAuthenticationProvider kerberosAuthenticationProvider() {
KerberosAuthenticationProvider provider =
new KerberosAuthenticationProvider();
SunJaasKerberosClient client = new SunJaasKerberosClient();
client.setDebug(true);
provider.setKerberosClient(client);
provider.setUserDetailsService(dummyUserDetailsService());
return provider;
}
#Bean
public SpnegoEntryPoint spnegoEntryPoint() {
//return new SpnegoEntryPoint("/login");
return new SpnegoEntryPoint();
}
#Bean
public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter(
AuthenticationManager authenticationManager) {
SpnegoAuthenticationProcessingFilter filter =
new SpnegoAuthenticationProcessingFilter();
filter.setAuthenticationManager(authenticationManager);
return filter;
}
#Bean
public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() {
KerberosServiceAuthenticationProvider provider =
new KerberosServiceAuthenticationProvider();
provider.setTicketValidator(sunJaasKerberosTicketValidator());
provider.setUserDetailsService(dummyUserDetailsService());
return provider;
}
#Bean
public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() {
SunJaasKerberosTicketValidator ticketValidator =
new SunJaasKerberosTicketValidator();
ticketValidator.setServicePrincipal("HTTP/localhost#fgao.fr");
ticketValidator.setKeyTabLocation(new
FileSystemResource("c:\\user\\tomcat.keytab"));
ticketValidator.setDebug(true);
return ticketValidator;
}
#Bean
public DummyUserDetailsService dummyUserDetailsService() {
return new DummyUserDetailsService();
}
I don't know if i have to specify the keytab file because on windows no keytab or kb5.conf file is needed so the c:\user\tomcat.keytab file is empty.
Can someone help me with this please
You will need a Keytab file.
Keytab file contains keys which are required by kerberos module to decrypt the incoming kerberos token.
Keytab file is not out of the box present as it is specific to a user account in AD.It has to be generated by your system admin and give it to you.
You will need a service user (dedicated for your application). Generate keytab for it.
Copy it on your application server and specify its path in spring.
Check ktpass command on windows for more details about creating keytab.
You may also need to check for krb5 conf file, what it contains and how you can specify it inside Spring.
Currently working on swarmifying our Springboot microservice back-end with eureka service discoverer. The first problem was making sure the service discoverer doesn't pick de ingress IP-adress but instead IP-address from the overlay network. After some searching I found a post that suggest the following Eureka Client Configuration:
#Configuration
#EnableConfigurationProperties
public class EurekaClientConfig {
private ConfigurableEnvironment env;
public EurekaClientConfig(final ConfigurableEnvironment env) {
this.env = env;
}
#Bean
#Primary
public EurekaInstanceConfigBean eurekaInstanceConfigBean(final InetUtils inetUtils) throws IOException {
final String hostName = System.getenv("HOSTNAME");
String hostAddress = null;
final Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface netInt : Collections.list(networkInterfaces)) {
for (InetAddress inetAddress : Collections.list(netInt.getInetAddresses())) {
if (hostName.equals(inetAddress.getHostName())) {
hostAddress = inetAddress.getHostAddress();
System.out.printf("Inet used: %s", netInt.getName());
}
System.out.printf("Inet %s: %s / %s\n", netInt.getName(), inetAddress.getHostName(), inetAddress.getHostAddress());
}
}
if (hostAddress == null) {
throw new UnknownHostException("Cannot find ip address for hostname: " + hostName);
}
final int nonSecurePort = Integer.valueOf(env.getProperty("server.port", env.getProperty("port", "8080")));
final EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils);
instance.setHostname(hostName);
instance.setIpAddress(hostAddress);
instance.setNonSecurePort(nonSecurePort);
System.out.println(instance);
return instance;
}
}
After deploying the new discoverer I got the correct result and the service discoverer had the correct overlay IP-address.
In order to understand the next step here is some information about the environment we run this docker swarm on. We currently have 2 droplets one for development and the other for production. Currently we are only working on the development server to Swarmify it. The production hasn't been touched in months.
The next step is to deploy a Discovery Client Springboot application that will connect to the correct service discoverer and also has the overly IP-address instead of the ingress. But when I build the application it always connects to our production service discoverer outside the docker swarm into the other droplet. I can see the application being deployed on the swarm but looking at the Eureka dashboard from the production server I can see that it connects to it.
The second problem is that the application also has the EurekaClient config you see above but it is ignored. Even the logs within the method is not called when starting up the applicaiton.
Here is the configuration from the Discovery Client application:
eureka:
client:
serviceUrl:
defaultZone: service-discovery_service:8761/eureka
enabled: false
instance:
instance-id: ${spring.application.name}:${random.value}
prefer-ip-address: true
spring:
application:
name: account-service
I assume that you can use defaultZone to point at the correct service discoverer but I can be wrong.
Just dont use an eureka service discoverer but something else like treafik. Much easier solution.
I tried to make the sample program for my project. It is LDAP with spring boot.
I tested it in my development environment. Then, it works well. However, when I test it in the deployment environment, It occurs socket closed error.
The difference is just the LDAP URL and password(I couldn't make a password of admin with special characters, eg. #, #).
So, I tried to access LDAP using ldapsearch in deployment environment. Then, I got some errors. However, when I search for this error, I couldn't search a suitable solution for me.
This is my spring configuration for access to LDAP.
#Bean
public ContextSource contextSource() {
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl("ldap://192.168.113.12");
contextSource.setBase("dc=test,dc=test");
contextSource.setUserDn("cn=admin,dc=test,dc=test");
contextSource.setPassword("test2019!#");
contextSource.afterPropertiesSet();
//for develop
// contextSource.setUrl("ldap://192.168.0.192");
// contextSource.setPassword("test2019");
PoolingContextSource pcs = new PoolingContextSource();
pcs.setDirContextValidator(new DefaultDirContextValidator());
pcs.setContextSource(contextSource);
TransactionAwareContextSourceProxy proxy = new TransactionAwareContextSourceProxy(pcs);
return proxy;
}
#Bean
public LdapTemplate ldapTemplate() {
return new LdapTemplate(contextSource());
}
This is error pictures when access to LDAP using spring LDAP.
This is error pictures using ldapsearch.
Help me.
ps. I didn't know how implemented the LDAP server, because it is installed by another team...
I would say the port is missing ;)
contextSource.setUrl("ldap://192.168.113.12:389");
Btw. in my opinion a nicer approach is to set the properties like this:
application.yml (or application.properties)
ldap:
contextSource:
url: ldap://192.168.113.12:389 #Local
base: dc=test,dc=test
userDn: cn=admin,dc=test,dc=test
password: test2019!#
and in the config class:
#Configuration
public class LdapConfiguration {
#Bean
#ConfigurationProperties(prefix="ldap.context-source")
public LdapContextSource contextSource() {
return new LdapContextSource();
}
#Bean
public ContextSource poolingLdapContextSource() {
PoolingContextSource pcs = new PoolingContextSource();
pcs.setDirContextValidator(new DefaultDirContextValidator());
pcs.setContextSource(contextSource());
TransactionAwareContextSourceProxy proxy = new TransactionAwareContextSourceProxy(pcs);
return proxy;
}
// other configs like ldaptemplate
}
I'm using JHipster to generate a microservice application made of
a gateway application with UI and without server: option --skip-server
a gateway application without UI and with server: option --skip-client
some microservices (type microservice
In order to generate everything I'm using a jdl file which looks like this:
application {
config {
applicationType gateway,
websocket spring-websocket,
clientFramework angularX,
skipServer true,
....
}
entities *
}
application {
config {
applicationType gateway,
packageName com.fginc.hermes.front,
websocket spring-websocket,
skipClient true
...
}
entities *
}
application {
config {
applicationType microservice,
}
entities A,B
}
application {
config {
applicationType microservice,
}
entities B,C
}
/** my entities **/
Everything works fine excepts that I would like the Angular websocket code (user-tracker) to be generated on the pure UI application.
Thank you for your help