I have a Spring Boot application with Github login using OAuth 2.0 .I followed the steps given here:
https://spring.io/guides/tutorials/spring-boot-oauth2/
My web page is a bit more complicated with header,main and footer frames.The issue is when I login successfully, I get redirected randomly to either the header.html,main.html or footer.html page.Instead I want to be redirected to the index.html which is my actual home page and displays all 3 frames correctly. How do I achieve this ?
The relevant code snippet:
index.html
...
<iframe src="./header.html" name="TradeFrameTop" height="90" width="100%" scrolling="no" style="border:none;"></iframe>
<iframe src="./contentHome.html" name="TradeMainContent" height="700" width="100%" scrolling="no" style="border:none;"></iframe>
<iframe src="./footer.html" name="TradeFrameBottom" height="58" width="100%" scrolling="no" style="border:none;"></iframe>
Application.java
...
#Override
protected void configure(HttpSecurity http) throws Exception{
http
.headers().frameOptions().sameOrigin()
.and()
.authorizeRequests(a -> a
.antMatchers("/","/error","/webjars/**").permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(e -> e
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
)
.csrf(c -> c
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
)
.logout(l -> l
.logoutSuccessUrl("/").permitAll()
)
.oauth2Login();
}
Also, is there a way to have both OAuth based and in-memory authentication in Spring Boot?How do I assign roles and authorities for these 2 pathways separately ?
Related
Good morning,
I am writing an application using Spring security (latest version) and Spring MVC (latest version).
After securying everything was ok, the form and the controller, together with Spring security configuration worked well and the login was always successful.
Then I added a custom css and some images to display a better graphic, here it came the problem:
everytime I login I am first redirected to the login.css file rather than the homepage, although the login is successful I first see a blank page with the url of the css.
Spring Security configuration
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
//configure security for pages
.antMatchers(new String[]{"/login", "/accessDenied"}).permitAll()
.antMatchers("/**").access("hasAnyRole('admin', 'operatore')")
.anyRequest().authenticated()
//creates login form
.and().formLogin().loginPage("/login").loginProcessingUrl("/login")
.defaultSuccessUrl("/home").failureUrl("/accessDenied")
.usernameParameter("id_utente").passwordParameter("password")
//catches exceptions http 403 response
.and().exceptionHandling().accessDeniedPage("/accessDenied");
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
Static resources are under the path /static/css and /static/images.
I read this problem comes from the fact that Spring security redirects you to the last requested url after login, as to resolve the issue I tried using
#Override
public void configure(WebSecurity web)
{
web.ignoring().antMatchers("/static/**");
}
but it didn't work.
Are there any way to solve this problem?
EDIT
I already tried using
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
//configure security for pages
.antMatchers("/static/**").permitAll()
.antMatchers(new String[]{"/login", "/accessDenied"}).permitAll()
.antMatchers("/**").access("hasAnyRole('admin', 'operatore')")
.anyRequest().authenticated()
//creates login form
.and().formLogin().loginPage("/login").loginProcessingUrl("/login")
.defaultSuccessUrl("/home").failureUrl("/accessDenied")
.usernameParameter("id_utente").passwordParameter("password")
//catches exceptions http 403 response
.and().exceptionHandling().accessDeniedPage("/accessDenied");
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
But I am anyhow redirected after a successufl login to a 404 page with url "http://localhost:8080/static/css/login.css". In the login page the static resources are corretcly served as the style is how I expect it to be.
EDIT #2
I Edited as Eleftheria Stein-Kousathana said, but it keeps redirecting to the css (showing the code inside this time) instead of the homepage.
The project structure is:
Resource handler is added this way:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}
and updated configuration is:
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
//configure security for pages
.antMatchers("/css/**", "/images/**").permitAll()
.antMatchers(new String[]{"/login", "/accessDenied"}).permitAll()
.antMatchers("/**").access("hasAnyRole('admin', 'operatore')")
.anyRequest().authenticated()
//creates login form
.and().formLogin().loginPage("/login").loginProcessingUrl("/login")
.defaultSuccessUrl("/home").failureUrl("/accessDenied")
.usernameParameter("id_utente").passwordParameter("password")
//catches exceptions http 403 response
.and().exceptionHandling().accessDeniedPage("/accessDenied");
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
Inside login page the css is linked this way:
<link rel="stylesheet" href="<c:url value="/static/css/login.css" />">
With the new antMatchers the result is not a 404 but the code inside the css. By the way, the linked css is not served anymore as style is not displayed correctly if I use the new configuration and "/static/css/login.css" or "/css/login.css", none of the two link work.
Since static/css and static/images are under the static directory, they will be served at /css and /images respectively.
You can permit all requests to those resources in your HTTP security configuration.
http.authorizeRequests()
.antMatchers("/css/**", "/images/**").permitAll()
// ...
In a spring boot 2 web site , user can decide to log via email/password (after created a account) or use facebook/google logi (oauth2)
Actually
user x connect via google... log out
user y try to connect via google but use user x session..
Logout is not done via google...
I would like logout support this use case
User x connect via google, logout.
User y, click to connect to google, need to enter user/password (don't want to connect via precedant user)
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/oauth_login", "/loginFailure", "/", "/logout")
.permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2Login()
.loginPage("/oauth_login")
.authorizationEndpoint()
.baseUri("/oauth2/authorize-client")
.authorizationRequestRepository(authorizationRequestRepository())
.and()
.tokenEndpoint()
.accessTokenResponseClient(accessTokenResponseClient())
.and()
.defaultSuccessUrl("/loginSuccess")
.failureUrl("/loginFailure")
.and()
.logout()
.logoutSuccessUrl("/")
.invalidateHttpSession(true);
}
If I remove .csrf().disable(), I get a 403 error. Don't understand why
html log out
Logout
<form id="logoutForm" action="/logout" method="post">
<input hidden type="submit" value="Sign Out"/>
</form>
Edit
seem to have a lot of thread with this kind of error...
like this one...
google account logout and redirect
seem like a token issue.
so just dangerous to use oauth on a public computer...
I am deploying a spring boot webapplication in AWS EC2 instance on port 80 and the home page is displayed as Secured When I click on the link like user login or admin login the browser shows it as Not Secured.What should I do to make my whole application secured.
Below is my code which I am using from a site,I am new to spring security,Please help.
Home.html
<div class="starter-template">
<h1>Spring Boot Web Thymeleaf + Spring Security</h1>
<h2>1. Visit <a th:href="#{/admin}">Admin page (Spring Security protected, Need Admin Role)</a></h2>
<h2>2. Visit <a th:href="#{/user}">User page (Spring Security protected, Need User Role)</a></h2>
<h2>3. Visit <a th:href="#{/about}">Normal page</a></h2>
</div>
#Configuration
// http://docs.spring.io/spring-boot/docs/current/reference/html/howto-security.html
// Switch off the Spring Boot security configuration
//#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AccessDeniedHandler accessDeniedHandler;
// roles admin allow to access /admin/**
// roles user allow to access /user/**
// custom 403 access denied handler
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/", "/home", "/about").permitAll()
.antMatchers("/admin/**").hasAnyRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
.and()
.withUser("admin").password("password").roles("ADMIN");
}
}
What am I doing wrong?Is the issue in the code or my AWS Configuration
Solved the issue by setting application.properties to the below
server.use-forward-headers=true
I would like to create custom pure html/js login page in Spring Security.
I use Spring Boot 1.2.5.RELEASE
I defined an application and configuration:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#Configuration
#EnableWebSecurity
#EnableWebMvcSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("a").password("a").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // DISABLED CSRF protection to make it easier !
.authorizeRequests()
.antMatchers("/", "/login.html").permit
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.permitAll()
.and()
.logout()
.permitAll()
.logoutUrl("/logout")
.logoutSuccessUrl("/");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
My login page looks like that (copied from default page!)
<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td> </tr>
</table>
</form></body></html>
But I still have: AUTHORIZATION_FAILURE
Is it possible to create pute html login page (without jsp, thymeleaf, etc.) ?
What do I do wrong in my code ?
You configured your login page to be at /login.html (using loginPage("/login.html")). This will also change the location to which you need to post the credentials to login. The documentation states:
If "/authenticate" was passed to this method [loginPage(String)] it update the defaults as
shown below:
/authenticate GET - the login form
/authenticate POST - process the credentials and if valid authenticate the user
/authenticate?error GET - redirect here for failed authentication attempts
/authenticate?logout GET - redirect here after successfully logging out
In order to make the login work, you need to make login.html post the credentials to /login.html instead of /login.
Is there a way to integrate Spring Security 4 (Mainly for managing user access levels and which views they can access) and JSF 2?
I found this neat thing which allows you to mix both Spring Boot, and JSF 2 with PrimeFaces 5. Great stuff. I want to see if you can kick it up another level.
Normally you would configure Spring Security for Spring MVC like so:
WebSecurityConfig.java
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("Zyst").password("password").roles("USER");
}
}
And then those would as far as I know, do correct me if I'm mistaken, look in your MvcConfig to see what it actually means by "/home" and the like:
MvcConfig.java
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
}
}
However, I've been googling for a few hours and cannot really find a conclusive answer how to configure Spring Security for JSF. Can you implement your front end using JSF and then make that managed by Spring Security, so, for example Links, ie: localhost:8080/home instead of localhost:8080/home.xhtml are properly managed and served? And so that user levels defined in WebSecurityConfig.java can only access pages relevant to themselves.
From what I've (briefly) investigated it might not be possible due to Faces and Mvc being different technologies that don't particularly play well together. However, if possible I'd like to make sure of whether it's possible or not.
And if it IS possible, can you provide either a working example, or a link to somewhere that goes more in depth? I did google quite a bit but it's 100% possible I ended up missing something.
Any and all answers are greatly appreciated.
There's no problem in using Spring Boot, Spring Security, JSF and Spring Core all together, in the end, JSF views are resolved as urls and that's what you work in Spring Security with. That's an example for the configuration in my own application, which I've pruned a bit to minimize the code amount. The code is self-explanatory:
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// Have to disable it for POST methods:
// http://stackoverflow.com/a/20608149/1199132
http.csrf().disable();
// Logout and redirection:
// http://stackoverflow.com/a/24987207/1199132
http.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.invalidateHttpSession(true)
.logoutSuccessUrl(
"/login.xhtml");
http.authorizeRequests()
// Some filters enabling url regex:
// http://stackoverflow.com/a/8911284/1199132
.regexMatchers(
"\\A/page1.xhtml\\?param1=true\\Z",
"\\A/page2.xhtml.*")
.permitAll()
//Permit access for all to error and denied views
.antMatchers("/500.xhtml", "/denied.xhtml")
.permitAll()
// Only access with admin role
.antMatchers("/config/**")
.hasRole("ADMIN")
//Permit access only for some roles
.antMatchers("/page3.xhtml")
.hasAnyRole("ADMIN", "MANAGEMENT")
//If user doesn't have permission, forward him to login page
.and()
.formLogin()
.loginPage("/login.xhtml")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/main.xhtml")
.and().exceptionHandling().accessDeniedPage("/denied.xhtml");
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
//Configure roles and passwords as in-memory authentication
auth.inMemoryAuthentication()
.withUser("administrator")
.password("pass")
.roles("ADMIN");
auth.inMemoryAuthentication()
.withUser("manager")
.password("pass")
.roles("MANAGEMENT");
}
}
Of course, this code works with *.xhtml suffixed urls, as they're served by the JSF Servlet. If you want to avoid this suffix, you should use a url rewriting tool as Prettyfaces. But that's another story that has already been widely discussed in StackOverflow.
Also, remember to target your login form to the configured login processing url to let Spring Security handle the authentication and redirection to your main page. What I usually do is to use a non-JSF form and apply the Primefaces styles on it:
<form id="login_form" action="#{request.contextPath}/login" method="post">
<p>
<label for="j_username" class="login-form-tag">User</label> <input
type="text" id="username" name="username" class="ui-corner-all"
required="required" />
</p>
<p>
<label for="j_password" class="login-form-tag">Password</label>
<input type="password" id="password" name="password"
class="ui-corner-all" required="required" />
</p>
<p>
<button type="submit"
class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only">
<span class="ui-button-text">Login</span>
</button>
</p>
</form>
See also:
Spring and JSF integration
Spring Boot JSF Integration