Spring Boot, OAuth2 with azure and another provider (e.g. google) - spring-boot

I have an application that is using Azure Active directory to authenticate and I need to add another provider, for example google.
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends AadWebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.anyRequest().authenticated();
}
}
spring:
cloud:
azure:
active-directory:
enabled: true
profile:
tenant-id:
# credential:
client-id:
client-secret:
security:
oauth2:
client:
registration:
google:
client-id:
client-secret:
Using above code will force azure login.
How can I adapt the code to have both options azure and google?

I did not manage to make it work with spring-cloud-azure-starter-active-directory, so I removed this plugin and used:
spring:
security:
oauth2:
client:
registration:
google:
client-id:
client-secret:
azure:
client-id:
client-secret:
scope:
- openid
- profile
- email
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/login/oauth2/code/azure
provider: azure-active-directory
provider:
azure-active-directory:
issuer-uri: https://login.microsoftonline.com/{tenant-id}/v2.0
This example helped me https://github.com/Azure-Samples/azure-spring-boot-samples/blob/spring-cloud-azure_v4.4.1/aad/spring-security/servlet/oauth2/login/src/main/resources/application.yml

Related

Spring Oauth2 Login not working after migrating to Spring Boot 3

After migration to Spring Boot 3 from 2.7.5, when trying to login and get into infinity loop in the login screen.
After debugging we found this exception:
org.springframework.security.oauth2.core.OAuth2AuthorizationException: [invalid_request] client_secret is must in DefaultAuthorizationCodeTokenResponseClient.getTokenResponse(OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest)
You can check our how is defined our SecurityFilter chain.
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers(new CsrfIgnoreRequestMatcher())
)
.headers(headers -> headers
.cacheControl().disable()
.frameOptions().disable()
)
//Access configuration
.authorizeHttpRequests(authorizeRequest -> authorizeRequest
.requestMatchers(HttpMethod.OPTIONS).permitAll()
.requestMatchers(
LOGIN,
LOGOUT).permitAll()
)
.exceptionHandling(exceptionHandling -> exceptionHandling
.authenticationEntryPoint(new Http401UnauthorizedEntryPoint())
)
//######## OAUTH2-Login configuration ########
.oauth2Login(oAuth2Login -> oAuth2Login
.authorizationEndpoint(authorizationEndpoint -> authorizationEndpoint
.baseUri(LOGIN)
.authorizationRequestResolver(customOAuth2AuthorizationRequestResolver)
)
.loginProcessingUrl(LOGIN)
.userInfoEndpoint(userInfo -> userInfo.userAuthoritiesMapper(new RoleMapper()))
)
.logout(logout -> logout
.logoutUrl(LOGOUT)
.invalidateHttpSession(true)
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK))
);
return http.build();
}
Here are our application.yaml properties for the security:
spring:
security:
oauth2:
client:
provider:
customIdp:
authorization-uri: https://sso.company/app/login
jwk-set-uri: https://sso.company/oauth/nam/keys
token-uri: https://sso.company/oauth/nam/token?resourceServer=IdentityProviderRSUE&
user-info-uri: https://sso.company/oauth/nam/userinfo
user-name-attribute: cn
customIdpSso:
authorization-uri: https://sso.company/app/login
token-uri: ${spring.security.oauth2.client.provider.customIdp.tokenUri}
user-info-uri: ${spring.security.oauth2.client.provider.customIdp.userInfoUri}
user-name-attribute: ${spring.security.oauth2.client.provider.customIdp.userNameAttribute}
registration:
customIdp:
authorizationGrantType: authorization_code
clientAuthenticationMethod: basic
client-id: custom-client-id
clientName: Custom
client-secret: custom-client-secret
provider: customIdp
redirect-uri: "{baseUrl}/api/login"
scope: portal
customIdpSso:
authorizationGrantType: ${spring.security.oauth2.client.registration.customIdp.authorizationGrantType}
clientAuthenticationMethod: ${spring.security.oauth2.client.registration.customIdp.clientAuthenticationMethod}
clientId: ${spring.security.oauth2.client.registration.customIdp.clientId}
clientName: ${spring.security.oauth2.client.registration.customIdp.clientName}
client-secret: ${spring.security.oauth2.client.registration.customIdp.clientSecret}
provider: customIdpnosso
redirect-uri: ${spring.security.oauth2.client.registration.customIdp.redirect-uri}
scope: ${spring.security.oauth2.client.registration.customIdp.scope}
We migrated to new Spring Boot version and stoped using WebSecurityConfigurerAdapter.
If you need more information please tell us.
Due to https://docs.spring.io/spring-security/reference/5.8/migration/servlet/oauth2.html#_clientauthenticationmethod, the value for clientAuthenticationMethod should now be:
clientAuthenticationMethod: client_secret_basic
UPDATE: I've created https://github.com/spring-projects/spring-security/issues/12585 to look into making this clearer.

spring boot Oauth Okta 404 on redirect

My Spring Boot app giving me an error as 404 after redirecting from the Okta server.
May I have some help to solve this. My configurations are as below.
This is my Okta server redirect
https://dev-40483106.okta.com/oauth2/default/v1/authorize?response_type=code&client_id=0oa3p7a86ycJ7olpP5d7&scope=openid%20email&state=xVpkZIPGaGqAQCZIMXZgTrbmKmHJbcKbtM95KO9RwVU%3D&redirect_uri=http://localhost:8082/mms-sso/auth&nonce=cPdNAYT4tQ9mAjhj4HUiynBEQVAnJHnBTIezqquOpJM
This is my Redirect URI where I am getting a 404 error
http://localhost:8082/mms-sso/auth?code=rOh9u2fwBTB7gasIMUgtjIDMs5_Sydqz-0O_jG5Qhj0&state=xVpkZIPGaGqAQCZIMXZgTrbmKmHJbcKbtM95KO9RwVU%3D
Below is the screenshot
[![error-404][1]][1]
spring:
security:
oauth2:
client:
registration:
okta:
client-id: clientId
client-secret: secret
scope: openid, email
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8082/mms-sso/auth
provider:
okta:
issuer-uri: https://dev-40483106.okta.com/oauth2/default
authorization-uri: https://dev-40483106.okta.com/oauth2/default/v1/authorize
resource:
server: http://localhost:8081
server:
port: 8082
servlet:
context-path: /ui-one
security config
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/login**", "/auth/**",
"/auth?**").permitAll().anyRequest().authenticated().and()
.oauth2Login();
Okta config
Sign-in redirect URIs - http://localhost:8082/mms-sso/auth
Sign out redirect URI - http://localhost:8082/mms-sso/, http://localhost:8082/mms-sso/logout
Controller for redirect
#GetMapping("/auth")
String home(#AuthenticationPrincipal OidcUser user) {
return "Welcome to MMS SSO";
}
Your controller mapping is for /auth but in redirect you specify it as /mmo-sso/auth.

Spring Cloud Config Server/Client Security Issue

I have following security configs in
Server application.yml
management:
security:
enabled: false
server:
port: 8888
spring:
cloud:
config:
server:
jdbc:
order: 1
sql: SELECT prop_key,value FROM xlabs.properties where application=?
and profile=? and label=?
datasource:
password: XXXXX
url: jdbc:postgresql://localhost:8000/finos?currentSchema=xlabs
username: XXXXX
profiles:
active: jdbc
security:
user:
name: mufg
password: mufg
In Client side.
client application.properties
server:
port: 8082
spring:
application:
name: config-server
cloud:
config:
label: latest
profile: development
uri: http://localhost:8888
username: mufg
password: mufg
With this settings
Config server security works fine I can access properties via http://localhost:8888/config-server/development/latest after entering username and passwords. But when I try to up client it says property not resolved. Any issue here?
Thanks.
After some times I am able to find out the answer. In Config server with only that configs the client side will be blocked. So have to disable csrf and allow any request like as follows.
just add sever side.
#Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/encrypt/**").authenticated()
.antMatchers("/decrypt/**").authenticated();
}
}
But Here default security will be disabled. Here problem is if username or password changed from client side authentication happens.

Failed to bind properties clientid to OAuth2ClientProperties$Registration

I am working on a spring boot app in order to communicate with another secured API.
For that, I implement a OAuth2RestTemplate with the following properties but it failed when I run the application.
#Configuration
#EnableOAuth2Client
class RestTemplateConfiguration {
#Bean
#ConfigurationProperties("oauth2")
public OAuth2ProtectedResourceDetails oAuth2ProtectedResourceDetails() {
return new ClientCredentialsResourceDetails();
}
#Bean
public OAuth2RestTemplate oAuth2RestTemplate(
#Qualifier("oAuth2ProtectedResourceDetails") OAuth2ProtectedResourceDetails oAuth2ProtectedResourceDetails) {
return new OAuth2RestTemplate(oAuth2ProtectedResourceDetails);
}
}
application.properties
spring:
security:
oauth2:
client:
registration:
clientId: xxxxxxxxxxxxxxxxxx
clientSecret: xxxxxxxxxxxxxxxxx
accessTokenUri: https://xxxxxx/oauth2/access_token
scope: openid profile xxxxxxxxxxx
authorizationGrantType: client_credentials
The exception I get when I run the code
Failed to bind properties under 'spring.security.oauth2.client.registration.clientid' to org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties$Registration:
I think the problem is here
security:
oauth2:
client:
registration:
mb:
client-name: mb
client-id: ui
client-secret: secret
authorization-grant-type: authorization_code
redirect-uri: http:localhost:8084/ui/login/oauth2/code/
scope: openId
client-authentication-method: basic
provider:
mb:
token-uri: http://localhost:8181/oauth/token
authorization-uri: http:localhost:8181/oauth/authorize
user-info-uri: http:localhost:8181/oauth/userinfo
user-name-attribute: name
I ran into the same issue. The reference documentation mentions that you need to provide a registrationId within the property "path"
You application.properties should look like this:
spring:
security:
oauth2:
client:
registration:
YOUR_REGISTRATION_ID: # <----------
clientId: xxxxxxxxxxxxxxxxxx
clientSecret: xxxxxxxxxxxxxxxxx
accessTokenUri: https://xxxxxx/oauth2/access_token
scope: openid profile xxxxxxxxxxx
authorizationGrantType: client_credentials

How to Secure Spring Cloud Config Server

I understand that a Spring Cloud Config Server can be protected using an user name and password , which has to be provided by the accessing clients.
How can i prevent the clients from storing these user name and
password as clear text in the bootstrap.yml files in the client
application/services ?
The very basic "basic authentication" (from here https://github.com/spring-cloud-samples/configserver)
You can add HTTP Basic authentication by including an extra dependency on Spring Security (e.g. via spring-boot-starter-security). The user name is "user" and the password is printed on the console on startup (standard Spring Boot approach). If using maven (pom.xml):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
If you want custom user/password pairs, you need indicate in server configuration file
security:
basic:
enabled: false
and add this minimal Class in your code (BasicSecurityConfiguration.java):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
//#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class BasicSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Value("#{'${qa.admin.password:admin}'}") //property with default value
String admin_password;
#Value("#{'${qa.user.password:user}'}") //property with default value
String user_password;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password(user_password).roles("USER")
.and()
.withUser("admin").password(admin_password).roles("USER", "ACTUATOR");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/encrypt/**").authenticated()
.antMatchers("/decrypt/**").authenticated()
//.antMatchers("/admin/**").hasAuthority("ROLE_ACTUATOR")
//.antMatchers("/qa/**").permitAll()
;
}
}
#Value("#{'${qa.admin.password:admin}'}") allow passwords to be defined in property configuration file, environment variables or command line.
For example (application.yml):
server:
port: 8888
security:
basic:
enabled: false
qa:
admin:
password: adminadmin
user:
password: useruser
management:
port: 8888
context-path: /admin
logging:
level:
org.springframework.cloud: 'DEBUG'
spring:
cloud:
config:
server:
git:
ignoreLocalSshSettings: true
uri: ssh://git#gitlab.server.corp/repo/configuration.git
This works for me.
Edit: Instead of the Class, you can put basic user configuration directly in application.yaml:
security:
basic:
enabled: true
path: /**
ignored: /health**,/info**,/metrics**,/trace**
user:
name: admin
password: tupassword
For Spring Boot 2 the configuration in application.yml are now under spring.security.* (https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#security-properties)
spring.security:
basic:
enabled: true
path: /**
ignored: /health**,/info**,/metrics**,/trace**
user:
name: admin
password: tupassword
Basic authentication configuration that works for me.
Server-side:
Needed depedency: org.springframework.boot:spring-boot-starter-security
bootstrap.yml
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: git#bitbucket.org:someRepo/repoName.git
hostKeyAlgorithm: ssh-rsa
hostKey: "general hostKey for bitbucket.org"
security:
user:
name: yourUser
password: yourPassword
Client-side:
bootstrap.yml
spring:
application:
name: config
profiles:
active: dev
cloud:
config:
uri: http://localhost:8888
username: yourUser
password: yourPassword
management:
security:
enabled: false
Sources: Spring doc security feautres, Spring cloud config client security
encrypted text can be placed in bootstrap.yml.
Check -> http://projects.spring.io/spring-cloud/spring-cloud.html#_encryption_and_decryption

Resources