Google drive API access for aplication testing - spring

I am working on an application which uses Google Oauth2 token and the purpose of application is to download specific file from logged user's Google Drive. I am wondering if there is any chance to test that before going to production environment. I've enabled Google Drive API in Google Cloud Platform created Oauth 2.0 Client ID.
I've got web application created using Java and Spring and authorisation works good. I do receive Oauth 2.0 token from Google Sign In but when I add a scope for Google drive which is the same one added in GCP I do receive following error:
Below is spring security google scope:
spring.security.oauth2.client.registration.google.scope=https://www.googleapis.com/auth/drive.readonly
And the spring security config:
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf()
.disable()
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/styles/**", "/webjars/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2Login()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/goodbye");
}
}
I found some information that if the registered application in GCP has sensitive scope it should goes through validation process but I want to test it first before going to production that's why I've left that in Testing Oauth consent and added testing user but it doesn't work.
Any ideas what might be wrong?
Reproducible example:
Register app in GCP.
Enable Google Drive API and generate Oauth2 credential.
Add auth/drive.readonly scope.
Set consent status to testing and add testing user.
Create Spring Boot app with Spring Security.
Add scope:
spring.security.oauth2.client.registration.google.scope=https://www.googleapis.com/auth/drive.readonly
Run app and authenticate with Google Sign in.

Related

Getting [invalid_id_token] Missing (required) ID Token in Token Response for Client Registration: github

I'm using SpringBoot and Oauth2 to authenticate on my application, using github for now.
If I use the scope oidc on application.properties the process works fine and github is used for he login.
My issue is that I want/need to use scope openid to get the id_token. When I change my application.properties to
spring.security.oauth2.client.registration.github.scope=openid
I start getting this error as response from login:
[invalid_id_token] Missing (required) ID Token in Token Response for Client Registration: github
I still get the http://localhost:8080/login/oauth2/code/github?code=ABC&state=CDE but right after that, the error shows up.
My security class is:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin").hasRole("ADMIN")
.antMatchers("/user").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.oauth2Login()
;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("springuser").password(passwordEncoder().encode("spring123")).roles("USER")
.and()
.withUser("springadmin").password(passwordEncoder().encode("admin123"))
.roles("ADMIN", "USER");
}
Any clue on what I should look to?
Thanks in advance
This
spring.security.oauth2.client.registration.github.scope=openid
activates OpenID Connect authentication, that's built on top of Oauth2.
But that's no longer just Oauth2, as it requires that token.
If Oauth2 is what you want, just remove the above line.
Yes it's just confusing, and that's probably why folks avoid OIDC.
I got it working!
Turns out the issue wasn't on the code. Problem was somehow on the github oauth2 credentials. When I used a token/secret generated by Google Credentials I didn't have to change anything else besides the application.properties.
The mistery about github login still remains, since there's not much data on the token register to be changed.

Spring Boot OAuth2 Single Sign On Concept not working

I am trying to develop OAuth2 Client Application with Single Sign On. I have already developed Authorization Server and tested with Client Credentials flow and its working fine. But when I try to use Authorization Code Grant with Single Sign On I could not get it right. Client application takes me to Login Screen when I access authenticated URL, but once authenticated I am redirected to call back url that's fine. But afterwards I could not access any URL as it all authenticated URL are automatically redirected to CALL BACK url. I have permitted call back url in my Security class
My requirement is once authenticated it will allow other urls normally before authentication it should not allow any url.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()
.authorizeRequests()
.antMatchers("/","/index.html", "/home.html", "/login**","/webjars/**", "/error**","/favicon.ico**","/oauth/token","/oauth/authorize**","/demo/1")
.permitAll()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and()
.httpBasic();
Here the call back url is demo/1 and Spring Security is not permitting any other url here.
My requirement is once authenticated it should allow other urls normally before authentication it should not allow any url.
http.authorizeRequests().antMatchers("/","/resources/**", "/**").permitAll().anyRequest().authenticated().and().formLogin()
.loginPage("/").permitAll().usernameParameter("username").passwordParameter("password")
.loginProcessingUrl("/j_spring_security_check").failureUrl("/")
.successHandler(myAuthenticationSuccessHandler()).and().logout().logoutSuccessUrl("/")
.logoutUrl("/logout").invalidateHttpSession(true).deleteCookies("JSESSIONID").and().csrf().disable().headers().frameOptions().sameOrigin();

How to single sign out on Spring mvc application enabled SSO using Spring OAuth2?

I'm developing a spring web app with SSO architect by using Spring OAuth2
2 spring mvc web apps
1 authorization server is responsible for SSO and issue/check tokens
1 resources server serving /api/me
Everything works well when single signing on, but I don't know how to Single Sign Out (1 app logs out, other apps log out as well). Currently, it seems that every apps with mimimum config like code snippet below is using different session storage, and after successful authentication, it saves the authenticated session in its own session storage, and every subsequent requests is intercepted with the session in cookie. So when sso-server logging out it cannot invalidate related sessions on others app session storages. Anyone could suggest me some strategies for Single Sign Out?
Web client application.yml file:
security:
oauth2:
client:
clientId: metlife_monitor
clientSecret: password
accessTokenUri: http://localhost:8668/sso-server/oauth/token
userAuthorizationUri: http://localhost:8668/sso-server/oauth/authorize
tokenName: oauth_token
resource:
userInfoUri: http://localhost:8688/api/me
Web Application class:
#SpringBootApplication
#EnableOAuth2Sso
#EnableJdbcHttpSession
public class Application extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login**", "/error**", "/webjars/**").permitAll()
.anyRequest().authenticated()
.and().logout()
.logoutUrl("/logout")
.logoutSuccessUrl("http://localhost:8668/sso-server/logout")
.invalidateHttpSession(true)
.deleteCookies("client-session", "JSESSIONID")
.permitAll()
.and().csrf().disable()
;
}
public static void main(String[] args) {
SpringApplication.run(App1Application.class, args);
}
}
There's difference between a Single-Sign-On(SSO) server and a Central-Authentication-Server(CAS). If the your auth server does not manage any sessions, it stops being an SSO server and just becomes a CAS.
In your case you can have your SSO server manage sessions and it can also distribute a session id that Resource Servers would verify with it before servicing the request. It does lead to a chatty system though. If you can live with a little latency post session-expiry, then you can make very short-lived tokens that are attached to the SSO and would not have to verify the token with every request, you'd only refresh a token is there's still a valid session.
If you can, consider using Keycloak. It has adapters for Java and Javascript applications as well

How to allow certain endpoint in spring security to be allowed without authentication?

I have Spring Boot Rest API web app in which I am using spring security to have most endpoints to require authentication.
This is part of code:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
....
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.requestMatchers()
.antMatchers("/oauth/token")
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated();
}
Can some one explain what each line begining with http.csrf means?
How can I modify above code so that enpoint /bars/pk can be allowed to be accessed without requiring authentication just as if there was no Spring Security ?
By default, Spring Boot activates protection against CSRF attack (Cross Site Request Forgery attack). The attack consists of a malicious site taking advantage of a user being alredy authenticated to a site (e.g. bank) in order to trick the user to do actions on that site (e.g. fund transfer).
The protection against the attack consists of the Spring Boot application sending a token with every response and expecting the token to be sent by the client on subsequent request. If the token is not received, Spring Boot returns an error.
Sometimes, you want to disable this behavior (at your own risks), so you use csrf.disable. You might find it convenient to disable csrf protection if you develop a Stateless API, and you have no way to link a POST request to any previous requests or session. But again, you need to consider this and reason about it carefully.
Please note that CSRF protection has not effect on GET requests. It only affects state chaning requests (e.g. POST, DELETE)
In order to allow your endoints to anyone, without requiring any authentication, you need to use
http.authorizeRequests().antMatchers("/**").permitAll();
EDIT
To specifically allow unauthorized requests to /bars/pk and keep the other elements unchanged, modify your code as follows :
http.csrf().disable()
.requestMatchers()
.antMatchers("/oauth/token")
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/bars/pk").permitAll()
.anyRequest().authenticated();
Here is a complete example:
httpSecurity.authorizeRequests()
.antMatchers(HttpMethod.GET)
.permitAll() // Allow all GET requests to go unauthenticated
.antMatchers(allowedResources)
.permitAll() // Allow all requests to go unauthenticated for the specified paths
.antMatchers(protectedResources).hasRole(USER)
.antMatchers(adminResources).hasRole(ADMIN)
.anyRequest().authenticated(); // Authenticate all other request paths

Using SAML with Spring Boot behind an ELB redirects to http instead of https

I'm trying to use Okta to authenticate users from a SpringBoot application.
I've setup the app following the Okta Tutorial from : https://developer.okta.com/blog/2017/03/16/spring-boot-saml
However my app is behind an ELB, and as such the TLS is being terminated at the LB. So I've modified the configuration from the tutorial to suit my needs.
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/saml*").permitAll()
.anyRequest().authenticated()
.and()
.apply(saml())
.serviceProvider()
.keyStore()
.storeFilePath(this.keyStoreFilePath)
.password(this.password)
.keyname(this.keyAlias)
.keyPassword(this.password)
.and()
.protocol("https")
.hostname(String.format("%s", serverName))
.basePath("/")
.and()
.identityProvider()
.metadataFilePath(this.metadataUrl);
}
This does the trick but there is a problem. After the user is authenticated by Okta, the user is finally redirected to a http URL instead of a https URL. I am thinking the reason for this is that the TLS is being terminated at the LB and my app is actually receiving the request with http which is being sent in the RelayState.
This is something I found : spring-boot-security-saml-config-options.md.
It contains a list of SAML properties for spring boot security. I added the following to the application.properties file
saml.sso.context-provider.lb.enabled = true
saml.sso.context-provider.lb.scheme=https
saml.sso.profile-options.relay-state=<https://my.website.com>
It doesn't change the http redirection. Is there something I am doing wrong?
When a SAML 2.0 IdP like Okta redirects back to you application the endpoint url is either based on the SAML 2.0 metadata you application expose or the configuration in the IdP.
Furthermore, it is optional to add a Destination property in SAML 2.0 AuthnRequest:
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified"
Destination="https://my.website.com" IssueInstant="2018-11-22T09:23:08.844Z" Version="2.0" ID="id-f8ee3ab1-6745-42d5-b00f-7845b97fe953">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion"> ... </Issuer>
...
</samlp:AuthnRequest>

Resources