I have a spring boot application in which I have integrated Azure AD authentication. The authorization url does not redirect to home page but keeps giving 401 unauthorized.
Below is application.properties:
ssoServiceUrl=https://login.microsoftonline.com/xxxxx
spring.security.oauth2.client.registration.azure.client-authentication-method=post
security.oauth2.client.client-id=xxxxxxx
security.oauth2.client.client-secret=xxxxxxx
security.oauth2.client.scope=openid https://graph.microsoft.com/user.read
security.oauth2.client.authentication-scheme=header
security.oauth2.client.client-authentication-scheme=form
security.oauth2.issuer=https://login.microsoftonline.com/xxxxxx/v2.0
security.oauth2.client.access-token-uri=${ssoServiceUrl}/oauth2/v2.0/token
security.oauth2.client.user-authorization-uri=${ssoServiceUrl}/oauth2/v2.0/authorize
security.oauth2.resource.user-info-uri=https://graph.microsoft.com/oidc/userinfo
below are the dependencies in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
App configure is as follows:
public void configure(HttpSecurity http) {
try {
http.antMatcher("/**")
.authorizeRequests()
.antMatchers("/error**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.logout()
.deleteCookies()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("https://login.microsoftonline.com/common/oauth2/logout?post_logout_redirect_uri=http%3A%2F%2Flocalhost%3A8080");
}
I followed this post and added spring.security.oauth2.client.registration.azure.client-authentication-method=post but that does not work. Also, changed the spring boot starter dependency versions but that also does not help.
Also followed this and changed azure endpoints from v2 to v1 but that also does not work. This is working fine on localhost. I am not able to collect any logs as this is happening after deployment to ECS service and errors out without touching application code.
Could you please try our latest version of azure-spring-boot-starter-active-directory? Which work for spring-boot 2.4.5.
Related
I am building one spring cloud gateway and in that I am implementing Keycloak Security everything works fine but need to do programmatically instead of writing in yml file there can be multiple Realms.
Below are the dependencies which I am using:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
And my application Api gateway start application code is as below:
#SpringBootApplication
#ComponentScan(basePackages = {"com", "com.b","com.auth","com.security"})
public class APIGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(APIGatewayApplication.class, args);
}
#Bean
public KeycloakConfigResolver keycloakConfigResolver() {
return new PathBasedKeycloakConfigResolver();
}
}
Security Config http code is as below:
#Configuration
public class SecurityConfig {
#Bean
public SecurityWebFilterChain springSecurityFilterChain (ServerHttpSecurity http) {
http
.authorizeExchange()
.anyExchange()
.authenticated()
.and()
.oauth2Login(); // to redirect to oauth2 login page.
return http.build();
}
}
and in my application.yml file I am adding below configuration:
spring:
security:
oauth2:
client:
provider:
my-keycloak-provider:
issuer-uri: http://localhost:8280/auth/realms/Default
registration:
keycloak-spring-gateway-client:
provider: my-keycloak-provider
client-id: Default
client-secret: 8ZRUH62Pfhfde6uqasD8dfgdhvqWt03K6
authorization-grant-type: authorization_code
redirect-uri: '{baseUrl}/app'
main:
web-application-type: reactive
application:
name: app
cloud:
gateway:
default-filters:
- TokenRelay
So we can in configuration file I am manually adding configs for one Realms but there can be multiple realms in that how to do it programmatically dynamic? .
In my Java 11, Spring Boot 2.7.3, Maven application, I am using Spring Security in order to authenticate my users. To do this, I included the following dependency in my pom.xml file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.7.3</version>
</dependency>
And then coded the following security configuration class:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
#EnableWebSecurity
#Configuration
public class SecurityConfiguration {
#Bean
public AuthenticationProvider authenticationProvider() {
return new DocumentumAuthenticationProvider();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/content/login")
.permitAll()
.and()
.logout()
.logoutUrl("/content/logout")
.logoutSuccessUrl("/content/logout")
.permitAll();
return http.build();
}
#Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().antMatchers("**/content/css/**" ,"/content/js/**" ,"/content/images/**" ,"/error/**");
}
#Bean
public BCryptPasswordEncoder encodePWD() {
return new BCryptPasswordEncoder();
}
}
Note that my custom authentication provider, DocumentumAuthenticationProvider, extends AbstractUserDetailsAuthenticationProvider. The user is prompted for credentials, which are then authenticated against a Documentum repository.
The above approach works fine.
Next, I wanted to implement SSO against Azure AD, so I removed the above security configuration class and custom authentication provider from the code set, and replaced the above pom.xml dependency with the following entries:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
</dependency>
I then added the following entries to my application.properties file, using values from a new application registration that I configured after logging into my Azure AD portal:
spring.cloud.azure.active-directory.enabled=true
spring.cloud.azure.active-directory.profile.tenant-id=xxxxxxxxxxxx
spring.cloud.azure.active-directory.credential.client-id=yyyyyyyyyyyy
spring.cloud.azure.active-directory.credential.client-secret=zzzzzzzzzz
Again, this all works fine.
The goal is now to have both these authentication approaches available together in my application and to make them switchable. Not surprisingly, if I simply merge the code snippets above all together, the application will not start because I have a WebSecurityConfigurerAdapter as well as SecurityFilterChain, which is not supportable:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalStateException: Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
... 21 common frames omitted
Caused by: java.lang.IllegalStateException: Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.
Many thanks for reading. I'd be very grateful for any suggestions / guidance as to how to proceed so that I can have both authentication providers sitting side by side in my code, with the ability to switch between them with a configuration setting.
this is my Security configuration file for resource server
#Configuration
#EnableWebSecurity
public class SecureSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(STATELESS)
.and()
.authorizeRequests()
.anyRequest()
.permitAll()
.antMatchers("api/**")
.authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}
}
and those are dependencies for spring boot application (resource server app.)
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-core</artifactId>
<version>5.5.3</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
here is the jwk-set-url in the config yml file, to which my application is connecting at start up
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: http://localhost:8083/.well-known/openid-configuration/jwks
And via postman now when I'm getting the token from auth server via postman and trying to request to my server, I'm getting this kind of error
Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: Couldn't retrieve remote JWK set: org.springframework.web.client.HttpClientErrorException$NotFound: 404 null", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"
who has faced such kind of issue?
Change the "Hostname Verification" to "none" in SSL properties tab.
I'd like to handle an authorization code grant flow with spring.
It "works" for the redirections, on arriving on my app, correctly redirected to openam, authN and grant authZ, submit, redirected to redirectUri.
But when I come back in the redirectUri, it seems Spring doesn't go inside my method (doesn't stop on my breakpoint), and the security context is probably empty, so not authenticated, so redirected back to auth.
Here's my config, am I missing something ?
REST api in Springboot, with angular frontend
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath />
</parent>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
#Configuration
#EnableWebSecurity
public class SecurityConfigOAuth2 extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()
.authorizeRequests()
.antMatchers("/REST/v1/authorization-code/**").permitAll()
.anyRequest()
.authenticated()
.and()
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.oauth2Login()
.and()
.oauth2Client()
;
}
}
server:
port: 8080
servlet:
context-path: /OAuth2Client
spring:
application:
name: OAuth2Client
security:
basic:
enabled: false
oauth2:
client:
registration:
openam:
clientId: MyClientId
scope:
- openid
- profile
- email
authorizationGrantType: authorization_code
---
spring:
profiles: dev
security:
oauth2:
client:
provider:
openam:
tokenUri: {openam-dev}/access_token
authorizationUri: {openam-dev}/authorize
userInfoUri: {openam-dev}/userinfo
tokenInfoUri: {openam-dev}/tokeninfo
jwkSetUri: {openam-dev}/jwk_uri
registration:
openam:
clientSecret: MyClientSecret-dev
redirectUri: "{baseUrl}/REST/v1/authorization-code/callback"
logging:
level:
org.springframework.security: DEBUG
org.springframework.web.client.RestTemplate: DEBUG
I am going to register my spring boot application to spring-boot-admin server.
Here is my SpringBootAdminApplication.java
#Configuration
#EnableAutoConfiguration
#EnableAdminServer
public class SpringBootAdminApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAdminApplication.class, args);
}
}
And pom.xml:
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-example</artifactId>
<version>1.0.5</version>
</dependency>
</dependencies>
and application.properties
server.port = 8080
Server is running now:
Now, in client side:
properties:
spring.boot.admin.url=http://localhost:8080
info.version=#project.version#
spring.application.name=rest-module
pom.xml:
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>1.3.0</version>
</dependency>
But, when i run the spring boot from client, i get this error:
Created POST request for "http://localhost:8080/api/applications"
Setting request Accept header to [application/json, application/json, application/*+json, application/*+json]
Writing [Application [id=null, name=rest-module, managementUrl=http://Hayatloo-PC:8082, healthUrl=http://Hayatloo-PC:8082/health, serviceUrl=http://Hayatloo-PC:8082]] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#1637320b]
Failed to register application as Application [id=null, name=rest-module, managementUrl=http://Hayatloo-PC:8082, healthUrl=http://Hayatloo-PC:8082/health, serviceUrl=http://Hayatloo-PC:8082] at spring-boot-admin (http://localhost:8080/api/applications): 400 Bad Request
Why id=null ?
You messed up the versions. Try to update the client and server to the same versions. We try too keep em compatible but from 1.0.x to 1.3.x you have no chance.
Btw current version is 1.3.2.
Additional you are using the sample as dependency. This indeed works, but I wouldn't recommend it. You better setup your server as described in the guide. http://codecentric.github.io/spring-boot-admin/1.3.2/