Welcome. Ask away! Unless otherwise specified we assume you're using the latest 5.x version of Spring Security
I'm trying to enable spring security only on the actuator endpoints, and allow all other requests, regardless of auth scheme to pass into the app code (which handles security in it's own regard).
Right now this is what I have:
@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
// NOTE: This will only add spring security to the actuator endpoints, all other endpoints will be handled
// by the JWT auth handling.
// https://stackoverflow.com/questions/38403740/authenticate-only-selected-rest-end-points-spring-boot
return http.authorizeExchange()
.pathMatchers("/actuator/**").authenticated()
.anyExchange().permitAll()
.and().httpBasic()
.and().csrf().disable()
.build()
}
@Bean
fun userDetailsService(): MapReactiveUserDetailsService {
return MapReactiveUserDetailsService(
User.withDefaultPasswordEncoder()
.username(actuatorAdminUsername)
.password(actuatorAdminPassword)
.roles("SUPERUSER")
.build()
)
}
This works to ensure that:
1) http basic auth can be used to access the actuator endpoints
2) any bearer request is passed through into the app code (which is what I want)
but doesn't allow an http basic auth request to pass through and be handled by my app code. I've tried a few different incantations to get it working as expected, but mostly get the current state or I get it to pass through http basic requests (at which case my auth on the actuator endpoints doesn't work). Any pointers?
@molexx How did you setup this? You need to create a custom AccessDeniedHandler
implementation and set it through HttpSecurity.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler)
. Then you can implement handle
method as you wish.
For example:
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
response.setStatus(HttpStatus.FORBIDDEN.value());
response.getWriter().write(objectMapper.writeValueAsString(responseBody));
Or, in your case, you can set content-type to text/plain
and write a String.
server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto
@reneschroeder0000
hi, what is the best way to mock an oauth2-openid connect server for my client? i would like to have something like a local test repository that doesnt need to query other services.
my current implementation is as follows:
@TestConfiguration class OAuth2TestConfiguration { @Bean fun getInMemoryReactiveClientRegistrationRepository( @Value("\${spring.security.oauth2.client.registration.foo.client-id}") clientId: String, @Value("\${spring.security.oauth2.client.registration.foo.client-secret}") clientSecret: String, @Value("\${foobar.token-uri}") tokenUri: String ): ReactiveClientRegistrationRepository { return InMemoryReactiveClientRegistrationRepository( ClientRegistration.withRegistrationId("foo") .tokenUri(tokenUri) .clientId(clientId) .clientSecret(clientSecret) .scope("doesnt matter here") .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) .build() ) } @Bean fun getServerOAuth2AuthorizedClientRepository( @Autowired authorizedClientService: ReactiveOAuth2AuthorizedClientService ): AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository { val repo = AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService) repo.setAnonymousAuthorizedClientRepository(UnAuthenticatedServerOAuth2AuthorizedClientRepository()) return repo } @Bean fun getInMemoryReactiveOAuth2AuthorizedClientService( @Autowired repository: ReactiveClientRegistrationRepository ): ReactiveOAuth2AuthorizedClientService = InMemoryReactiveOAuth2AuthorizedClientService(repository) @MockBean lateinit var jwtDecoder: ReactiveJwtDecoder }
and wiremock for the tokenUri:
{ "request": { "method": "POST", "url": "/token" }, "response": { "status": 200, "headers": { "Content-Type": "application/json" }, "jsonBody": { "access_token": "some token", "token_type": "Bearer" } } }
Have you guys found a way to do Unit Testing on either @OAuth2Client or @ResourceServer mode when using WebFlux? spring-security-test
examples (https://docs.spring.io/spring-security/site/docs/current/reference/html/test.html#test-method) only demonstrate how to mock Basic Auth.
If there's a RTFM link, I would appreciate it as well.
redirectUris
for a mobile application.window.location.origin
but It does not work. Any idea please. (I am using ionic 4 as front end client). For dev I set http://localhost:8100
and It works.
I'm trying to add a token granter with spring-security-oauth2, but it seems to be very difficult. The default one is an anonymous class that wraps a CompositeTokenGranter
created on first use. There's no way to modify the list of granters it will use, nor modify them after it's been made. To construct any granter (in order to set one onAuthorizationServerEndpointsConfigurer
) you need to already have three other of the objects managed by that configurer.
Am I missing something?
@Bean
public TokenGranter internalTokenGranter(AuthorizationServerEndpointsConfiguration endpoints)
throws ReflectiveOperationException
{
AuthorizationServerEndpointsConfigurer configurer = endpoints.getEndpointsConfigurer();
TokenGranter tokenGranter = configurer.getTokenGranter();
tokenGranter.grant(null, null);
Field field = tokenGranter.getClass().getDeclaredField("delegate");
field.setAccessible(true);
CompositeTokenGranter compositeTokenGranter = (CompositeTokenGranter) field.get(tokenGranter);
compositeTokenGranter.addTokenGranter(new InternalTokenGranter(
configurer.getTokenServices(),
configurer.getClientDetailsService(),
configurer.getOAuth2RequestFactory()
));
return tokenGranter;
}
@OrangeDog There are different ways to solve this, I'm just showing you one way.
The Cloud Foundry UAA project created a class called AddTokenGranter
(link)
The library exposes the composite granter as oauth2TokenGranter
, in the UAA xml they add token granters in 3 different places as such:
<bean id="addUserTokenGranter"
class="org.cloudfoundry.identity.uaa.oauth.token.AddTokenGranter">
<constructor-arg name="userTokenGranter" ref="userTokenGranter"/>
<constructor-arg name="compositeTokenGranter" ref="oauth2TokenGranter"/>
</bean>
Hello,
I am trying to secure my /api/* via OAuth2 Authroization Code, I have the oauth2 working for endpoint
http://localhost:8080/ where the redirect url is http://localhost:8080/login/oauth2/code/azure
but when I try to hit http://localhost:8080/api/user , I get
"The reply url specified in the request does not match the reply urls "
where the redirect_uri=http://localhost:8080/api/user
Here is my SecurityConfig
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login();
THanks @OrangeDog I was trying to write an OAuthClient, redirect the user to login against Azure Active Directory and then provide access to my /api/* upon successful login
I was able to do that now, but when I try to do
String response = oAuth2RestTemplate.getForObject("https://graph.microsoft.com/v1.0/me", String.class);
This request is redirecting again to Azure AD and failing at "The reply url specified in the request does not match the reply urls "
I thought oAuth2RestTemplate does not redirect to Azure AD when accessing graph API instead, it will use the same access token obtained earlier