I'm using Stormpath for authentication in my website (developed with Spring Boot), but sometimes I receive ERR_TOO_MANY_REDIRECTS error. This happens every time I do the following:
1) Login to the website
2) Logout
3) Go to create a new user
4) Type the new user information
5) Click on create
The user is created, but the browser gives me ERR_TOO_MANY_REDIRECTS, and doesn't open anything. The only way to make it work again, is to clean the cookies and login again.
I'm using Spring Boot, so here's my configuration:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import static com.stormpath.spring.config.StormpathWebSecurityConfigurer.stormpath;
#Configuration
public class SpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.apply(stormpath());
}
}
Any idea why this is happening?
Thank you!
Never mind. The problem was with my stormpath version. I've updated it, and it's working great now. I was using an old version (1.0 RC6).
Related
I have deployed a war file generated by spring boot application using oauth2 for single sign on using Azure App service (https only).
When I browse to the home page, the home page loads with a login button.
On clicking the login button a redirect is happening to "http://..../login" (/login is the default sso login path) Since my app service is https only, the http url does not work.
I have tried the redirect_uri settings in the application.property file, but it is not helping.
Has anybody faced this problem?
How can it solved?
I found a similar issue mentioned here
This problem happens when your Tomcat server is behind a proxy. The HTTPS requests terminate at the proxy and the proxy then uses HTTP protocol to communicate to your Tomcat server. You will face this if you deploy your code on cloud providers like Azure (App Service), etc.
For anyone facing this problem, here is the solution:
in application.properties file, add the following. Note: some of the properties have different names in Spring Boot 2.* versions.
security.oauth2.client.pre-established-redirect-uri=https://yourappurl.net/login
security.oauth2.client.registered-redirect-uri=https://yourappurl.net/login
security.oauth2.client.use-current-uri=false
server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto
server.tomcat.use-relative-redirects=true
server.use-forward-headers=true
server.tomcat.internal-proxies=.*
In your SpringBootApplication class, add the following bean. With Spring Boot <= 2.1.x you had to provide a ForwardedHeaderFilter-Bean. Since Spring Boot 2.2.0 you don't have to do this anymore.
import org.springframework.core.Ordered;
import org.springframework.web.filter.ForwardedHeaderFilter;
#Bean
FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
final FilterRegistrationBean<ForwardedHeaderFilter> filterRegistrationBean = new FilterRegistrationBean<ForwardedHeaderFilter>();
filterRegistrationBean.setFilter(new ForwardedHeaderFilter());
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistrationBean;
}
Add the following line in configure method of your AppConfiguration class:
http.requiresChannel().anyRequest().requiresSecure();
For official info visit this page.
Ranbir has well explained the usecase where someone will face this problem.
I didnt have to add any additional properties to my springboot project. I just had to add ForwardedHeaderFilter as part of spring configuration and mentions the urls where I want this filter to act on x-forwarded header:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import javax.servlet.DispatcherType;
import org.springframework.core.Ordered;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.web.filter.ForwardedHeaderFilter;
import java.security.Security;
import java.util.Arrays;
#SpringBootApplication(scanBasePackages = {"com.abc.xyz"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
log.info("--- Security Overrides ---");
log.info("networkaddress.cache.ttl =" + Security.getProperty("networkaddress.cache.ttl"));
}
#Bean
public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
registration.setDispatcherTypes(javax.servlet.DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
registration.setUrlPatterns(Arrays.asList("/app/*", "/ping", "/oauth2/authorization/callback", "/oauth/callback"));
return registration;
}
}
Here are some useful references to follow:
https://tomgregory.com/spring-boot-behind-load-balancer-using-x-forwarded-headers/
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#filters-forwarded-headers
https://docs.spring.io/spring-boot/docs/2.0.1.RELEASE/reference/htmlsingle/#howto-enable-https
I have an application with a React FrontEnd and a spring boot backend. Here is my problem: I have to autorize my frontend in my back with my microsoft token. From here I manage to :
From my front page when I click on my login button it redirect me to
azure connection portal (I used msal.js library)
After the redirection, I have an access token.
Now, I want to send this access token to my back (something like /api/auth), call the microsoft graph api to retrieve users informations, create the user in my DataBase if he doesn't exists and then return information with a token that will allow my front to be authorized when it requests protected endpoints
Please use these samples for your reference. Mostly we will use either of the ADD resource server approach.
Hope you have the necessary dependencies in your application(azure-core, azure-spring-boot-starter-active-directory, spring-boot-starter-oauth2-client, spring-boot-starter-oauth2-resource-server and the normal spring web dependency).
The JWT token which you recived through frontend can be attached as a barer token with each request you are making to the spring boot app.
Include the below class for validating the azure JWT token.
import com.azure.spring.aad.webapi.AADJwtBearerTokenAuthenticationConverter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.WebSecurityConfigurerAdapter;
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests((requests) -> requests.anyRequest().authenticated())
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(new AADJwtBearerTokenAuthenticationConverter());
}
}
In case you come acorss with corss issue please add a filter to attach corss orgin in header.
Hope it will help.
Spring Security can be used to validate the token, you can take a look at this sample.
I am new to sending email using java. I have a Spring Boot project from where I want to send email. I have tried several examples available on internet. Giving the URL of two examples which I tried:
https://www.mkyong.com/spring-boot/spring-boot-how-to-send-email-via-smtp/
https://www.mkyong.com/java/javamail-api-sending-email-via-gmail-smtp-example/
But none is working. Can anyone say me what customizations I will have to do in these examples and which values I will have to change to make them working? Like I will change the to Address to the adress where I will have to send email, what is the username and password? Whose username, password are they?
You can use Sendgrid API. You can send 100 email per day without paying it's absolutely free. Need to create Sendgrid account and generate an API key to send emails.
Reference:
https://sendgrid.com/docs/for-developers/sending-email/v3-java-code-example/
There is Ogham library. The code to send email is easy to write and you can even use a template to write the content of your email. It is easier to use than other libraries because you don't need to handle technical concerns (like inlining images and styles in the HTML, it is done automatically).
You can even test your code locally with a SMTP server to check the result of your email before sending it through a SMTP provider.
The email can be sent either using SMTP protocol or through providers API (like SendGrid).
It is compatible with Spring Boot and even easier to use because you don't need to instantiate the service.
package fr.sii.ogham.sample.springboot.email;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import fr.sii.ogham.core.exception.MessagingException;
import fr.sii.ogham.core.service.MessagingService;
import fr.sii.ogham.email.message.Email;
#SpringBootApplication
#PropertySource("application-email-basic.properties") // just needed to be able to run the sample
public class BasicSample {
public static void main(String[] args) throws MessagingException {
SpringApplication.run(BasicSample.class, args);
}
#RestController
public static class EmailController {
// Messaging service is automatically created using Spring Boot features
// The configuration can be set into application-email-basic.properties
// The configuration files are stored into src/main/resources
#Autowired
MessagingService messagingService;
#PostMapping(value="api/email/basic")
#ResponseStatus(HttpStatus.CREATED)
public void sendMail(#RequestParam("subject") String subject, #RequestParam("content") String content, #RequestParam("to") String to) throws MessagingException {
// send the email using fluent API
messagingService.send(new Email()
.subject(subject)
.body().string(content)
.to(to));
}
}
}
There are many other features and samples / spring samples.
I'm trying to connect a Spring Boot app running locally/not in Google app engine when deployed to my Google DataStore. I am using Objectify and Google Remote API as my understanding is that Objectify will only work if deployed in App engine(?). The problem is that the Google Remote API is throwing 404 when I try and communicate with the DataStore. I think I might have my config wrong in spring boot as the instructions on the google docs talk about setting up config in web.xml which I don't use on my JAR based spring boot app. I have created a SpringBootServletInitializer class to try and register the servlet (code at the bottom). I'm coming at this from an AWS perspective and so far I've found Google cloud to be a nightmare! Connecting to DynamoDB is so much simpler and I feel I must be missing something!
import com.google.apphosting.utils.remoteapi.RemoteApiServlet;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Thomas on 01/07/2017.
*/
#Configuration
public class GoogleRemoteApiConfig extends SpringBootServletInitializer {
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(GoogleRemoteApiConfig.class, "/remote_api");
}
#Bean
public ServletRegistrationBean remoteApiRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(new RemoteApiServlet(), "/remote_api");
Map<String,String> params = new HashMap<String,String>();
registration.setInitParameters(params);
registration.setLoadOnStartup(1);
registration.setUrlMappings(Arrays.asList("/remote_api"));
registration.setName("RemoteApiServlet");
return registration;
}
}
I'd fundamentally misunderstood how the remote-api worked, and didn't realise I needed an app running in app engine to proxy the requests on to Google DataStore. I'm still confused that there is no simple way to access DataStore from Java but this approach is at least working!
Could everyone show me a tutorial on how to make Spring 3.1.1 running on Google App Engine, please?
I've followed severals tutorial and managed to get the dead simple HelloWorld example to work on App Engine. However, when I go futher, I stuck at the persistent process between Spring and Datastore. I looked at this thread Configuring JDO in Spring 3.1?, too, but it works on localhost but it doesn't work when I deploy to app engine due to the javax.naming.NamingException.
Therefore, I'm looking for a not-too-simple tutorial that covers basic aspects of a real life application such as the view, the model and the database.
Jappstart is a good place to see a working example of GAE that uses Spring and the Datastore (via JPA) and is also a good starting point for building a basic GAE/J app.
Having spent about a day trying to make this work, I thought I'd add some additional useful information here. First take a look at this project https://github.com/hleinone/spring-gae-jdo and this issue: http://code.google.com/p/googleappengine/issues/detail?id=1240 -- comment 24 is the useful one.
In case anyone wants to get this working with annotation-driven configuration, here's how I did it:
package com.domain.yourcode.configuration;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jdo.GAETransactionAwarePersistenceManagerFactoryProxy;
import org.springframework.orm.jdo.JdoTransactionManager;
//import org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy;
#Configuration
public class JDOConfiguration {
private static final PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("transactions-optional");
#Bean
public GAETransactionAwarePersistenceManagerFactoryProxy proxyPmf() {
GAETransactionAwarePersistenceManagerFactoryProxy proxy =
new GAETransactionAwarePersistenceManagerFactoryProxy();
proxy.setTargetPersistenceManagerFactory(pmf);
proxy.setAllowCreate(false);
return proxy;
}
#Bean
public JdoTransactionManager transactionManager() {
JdoTransactionManager mgr = new JdoTransactionManager();
mgr.setPersistenceManagerFactory(pmf);
return mgr;
}
}
You'll still want <tx:annotation-driven/> in your applicationContext.xml