Our Spring Boot application acts as an OAuth2 client and, by default, contacts the identity provider's (here: Keycloak) endpoint for its "OAuth Well-Known Configuration Information" configured by this Spring property:
spring.security.oauth2.client.provider.keycloak.issuer-uri
The problem is, that any #SpringBootTest then also attempts to connect to such a server which fails immediately. So, for integration testing, I'd like to replace the above issuer-uri with the propeties jwk-set-uri, authorization-uri and token-uri which don't prevent the application from starting.
So, I created the following application.yml which does its job but I think it's not very obvious for other team members what happens here.
spring:
security:
oauth2:
client:
registration:
keycloak:
provider: keycloak
client-id: ${app.authentication.client-id}
client-secret: ${app.authentication.client-secret}
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/keycloak"
scope: openid
provider:
keycloak:
user-name-attribute: preferred_username
---
spring:
config:
activate:
on-profile: default
security:
oauth2:
client:
provider:
keycloak:
issuer-uri: ${app.authentication.server-url}
---
spring:
config:
activate:
on-profile: integration-test
security:
oauth2:
client:
provider:
keycloak:
jwk-set-uri: ${app.authentication.server-url}
authorizationUri: ${app.authentication.server-url}
tokenUri: ${app.authentication.server-url}
Is there soem other apporach how to diable the issuer-uri and replace it by the three above properties when testing?
Related
My Spring Boot application contains the following property in src/main/resources/application.yml:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: ${AUTH_SERVER_METADATA_URL:http://localhost:8080/auth/realms/demo}
When running tests, e.g. #WebMvcTest, I don't have a running authorization server. Thus, I need to use the following configuration which I put into src/test/resources/application-test.yml and activate it by using the #ActiveProfiles("test") annotation.
spring:
security:
oauth2:
resourceserver:
jwt:
public-key-location: classpath:public_rsa.key
The problem is, that the application context loads both of the application property files which leads to a refused connection during the tests. Is it possible to selectively ignore the issuer-uri property during tests?
If you rename src/test/resources/application-test.yml to src/test/resources/application.yml, it should override the file src/main/resources/application.yml
I am encountering a very peculiar problem in spring cloud gateway. Every alternate request returns a 404. This happens across all services I've configured in the api-gateway without exception. I don't even know where to start to debug this problem.
Here's my application.yml file for common config.
server:
port: 8080
ssl:
enabled: true
key-store: classpath:keystore.p12
key-store-password: password
key-store-type: pkcs12
key-alias: tomcat
security:
require-ssl=true:
logging:
level:
org:
springframework:
cloud.gateway: DEBUG
http.server.reactive: DEBUG
web.reactive: DEBUG
spring:
application:
name: api-gateway
cloud:
gateway:
httpclient:
ssl:
useInsecureTrustManager: true
Here's my java config file
#EnableWebFluxSecurity
public class SecurityConfig {
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http,
ReactiveClientRegistrationRepository clientRegistrationRepository) {
// Authenticate through configured OpenID Provider
http.oauth2Login();
// Also logout at the OpenID Connect provider
http.logout(logout -> logout.logoutSuccessHandler(new OidcClientInitiatedServerLogoutSuccessHandler(
clientRegistrationRepository)));
// Require authentication for all requests
http.authorizeExchange().anyExchange().authenticated();
// Allow showing /home within a frame
http.headers().frameOptions().mode(Mode.SAMEORIGIN);
// Disable CSRF in the gateway to prevent conflicts with proxied service CSRF
http.csrf().disable();
return http.build();
}
}
Here's the spring profile specific config file that gets loaded on top of the common application.yml file.
spring:
security:
oauth2:
client:
provider:
keycloak:
issuerUri: http://localhost:9080/auth/realms/mylocal
userNameAttribute: preferred_username
registration:
keycloak:
clientId: api-gateway-client
clientSecret: abcdefgh-ijkl-mnop-qrst-uvwxyz5d6a9
cloud:
gateway:
default-filters:
- TokenRelay
routes:
- id: news
uri: http://localhost:8082/news
predicates:
- Path= /news/**
- id: customers
uri: http://localhost:8083/customers
predicates:
- Path= /boards/**
- id: search
uri: http://localhost:8085/search
predicates:
- Path= /search/**
Hey i got the issue recently too, I figure out that it was the load balancing the issue. Make sure that your spring.application.name of the microservice that you try to contact are all in capital letter (EXAMPLE) especially if you use Eureka. (hope it helps)
I had a similar issue. The reason was in registration of several services under the same application name in my Eureka server. Just like this:
Eureka instances screenshot
Those are completely different services, but they are registered under one application name. So when a request is made through load balancer, the latter tries to use both of the service urls. One service is able to serve request correctly, but another one may know nothing about the requested path, that is why 404 is returned.
Check if there are two or more microservices using the same spring.application.name and registered with eureka.
I know it's an old question... But might help future readers.
hey, here is the simplest solution I found for myself, in the browser
url, instead of 'localhost', give your system's name.
ex:
http://hp:8083/SERVICE-NAME/customers/**
also make sure to name all your spring application in uppercase.
I am facing with below error while accessing to api within OAuth2.0 credentials.
The examples on Internet containing user-info-uri credential, but I have only authorization-uri and token-uri. How can I successfully connect without user-info-uri ?
Authorization screen is successfully opened, but after that the error is shown:
[missing_user_info_uri] Missing required UserInfo Uri in UserInfoEndpoint for Client Registration: aa-client-1
My application.yml like this :
spring:
security:
oauth2:
client:
registration:
aa-client-1:
client-id: XXXX-XXXXX-XXXX-XXX
client-secret: XXXX-XXXXX-XXXX-XXX
provider: A
scope: A:scope
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/login
provider:
A:
authorization-uri: https://someurls/authorize
token-uri: https://someurl/token
I want to login the API without user-info-uri.
Unfortunately, you must provide an user-info-uri if your grant type is authorization_code.
See GitHub discussion and Spring Security Source Code.
Perhaps this workaround may also applicable to your context.
I'm using Sprig boot 2 M5 and spring oauth
I have this configuration for my oauth client app
security:
oauth2:
client:
registration:
my-client:
client-id: blabla
client-secret: asecret
client-name: a name
provider: my-provider
scope: read
redirect-uri: https://localhost:8780/dp
authentication-method: basic
authorization-grant-type: authorization_code
provider:
my-provider:
authorization-uri: https://blabla/oauth-server/oauth/authorize
token-uri: https://blaba/oauth-server/oauth/token
user-info-uri: https://lmfr:8780/user
user-name-attribute: username
I was expecting to be redirected to the login page of my Oauth provider but instead I get redirected to the default spring login page.
any suggestion ?
Remove the redirect-uri then it should work
See also this bug
I have created a Single Page Application using the Spring Tutorial for making one with AngularJS and OAuth and such found here:
https://spring.io/guides/tutorials/spring-security-and-angular-js/#_multiple_ui_applications_and_a_gateway_single_page_application_with_spring_and_angular_js_part_vi
This is the application.yml files for the SPA application:
security:
user:
password: none
oauth2:
client:
accessTokenUri: localhost:7777/uaa/oauth/token
userAuthorizationUri: localhost:7777/uaa/oauth/authorize
clientId: acme
clientSecret: acmesecret
resource:
user-info-uri: localhost:7777/uaa/user
zuul:
routes:
resource:
path: /resource/**
url: localhost:9000/resource
user:
path: /user/**
url: localhost:7777/uaa/user
eureka:
client:
serviceUrl:
defaultZone: ${vcap.services.eureka-service.credentials.uri:127.0.0.1:8761}/eureka/
---
spring:
profiles: cloud
eureka:
instance:
hostname: ${APPLICATION_DOMAIN}
nonSecurePort: 80
I want to know how I would change the zuul routes and the user-info-uri so that I don't have to specify the urls and all this can be done by using the service-id. I looked at the tutorial for using eureka here:
https://spring.io/blog/2015/01/20/microservice-registration-and-discovery-with-spring-cloud-and-netflix-s-eureka
but I don't quite understand how I can achieve my goal without adding all the java to my code, because the basic eureka server already seems to register all my services.
Had issue with using eureka service id, userInfoUri used to throw UnknownHost Exception all the time, #LoadBallanced restTemplate did not solve my issue, solution was to set prefer-token-info to false ( if true - no load ballancing for oauth )
security.oauth2.resource.service-id={Service ID as at eureka server registered}
security.oauth2.resource.userInfoUri= http://${security.oauth2.resource.service-id}/user/me
security.oauth2.resource.loadBalanced=true
security.oauth2.resource.prefer-token-info=false
no port number needed if service ID used , but needed if ip or host used
If I do understand your question correct you can just use the config file in this pattern:
zuul:
routes:
<service_id>:
path: /path/**
For example (if your oauth-service is registered as auth):
zuul:
routes:
auth:
path: /user/**
Zuul will leverage Eureka and find the endpoints for the services. In addition to that it will provide client-side load-balancing.