Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have a Spring Boot 1.3.0 application with Spring Security OAuth included as a sort of SSO integration.

The problem is that the application is running in a non-SSL environment with a non-standard port behind a load balancer (F5) that forces SSL and the OAuth provider requires all redirect URLs be registered as https, but the Spring OAuth client (auto-configured with @EnableOAuthSso) will only redirect to the OAuth provider with the following URL...

https://[provider_host]/oauth/authorize?client_id=[redact] &redirect_uri= http://[application_host]/login &response_type=code&scope=[redact]&state=IpMYTe

Note that the return redirect_uri is generated as http. Even though the F5 will force it to https on the way back, our OAuth provider will not allow a non-SSL redirect URI. How can I configure this?

With the exception of my Spring Data JPA controllers, this is the entirety of the app...

AppConfig.java

@SpringBootApplication(exclude = { HibernateJpaAutoConfiguration.class })
@EnableJpaRepositories
public class AppConfig extends SpringBootServletInitializer {
    public static void main(final String... args) {
        SpringApplication.run(AppConfig.class, args);
    @Autowired
    public DataSource dataSource;
    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean getEntityManagerFactoryInfo() {
        final LocalContainerEntityManagerFactoryBean fac = new LocalContainerEntityManagerFactoryBean();
        fac.setDataSource(dataSource);
        fac.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        fac.setPackagesToScan("[redact]");
        final Properties props = new Properties();
        props.put("hibernate.dialect", "org.hibernate.dialect.SQLServerDialect");
        props.put("hibernate.show_sql", "true");
        props.put("hibernate.format_sql", "true");
        fac.setJpaProperties(props);
        return fac;
    @Bean(name = "transactionManager")
    public PlatformTransactionManager getTransactionManager() {
        final JpaTransactionManager transactMngr = new JpaTransactionManager();
        transactMngr.setEntityManagerFactory(getEntityManagerFactoryInfo().getObject());
        return transactMngr;

SecurityConfig.java

@Configuration
@EnableOAuth2Sso
public class SecurityConfig {

application.properties

server.port=9916
server.contextPath=
server.use-forward-headers=true
security.oauth2.client.clientId=[redact]
security.oauth2.client.clientSecret=[redact]
security.oauth2.client.scope=[redact]
security.oauth2.client.accessTokenUri=https://[provider_host]/oauth/token
security.oauth2.client.userAuthorizationUri=https://[provider_host]/oauth/authorize
security.oauth2.resource.userInfoUri=https://[provider_host]/oauth/me
security.oauth2.resource.preferTokenInfo=false
logging.level.org.springframework=TRACE
                I am having a similar problem, but instead of wanting to be HTTPS, the URI is always returned to me as HTTPS when I want HTTP. Would you know how to do this same thing but in the opposite direction? I've already applied your answer to the application.properties file with no luck.
– user2465164
                Jun 8, 2016 at 14:04

After digging manually through the configuration classes I was able to find and add the following, which did the trick...

security.oauth2.client.pre-established-redirect-uri=https://[application_host]/login
security.oauth2.client.registered-redirect-uri=https://[application_host]/login
security.oauth2.client.use-current-uri=false

I'm not convinced there isn't a better way to solve the problem of forcing a HTTPS redirect URL, but this fix worked for me.

@Mark No, I found information about these by digging through the Spring properties metadata to see which beans they mapped to. Unfortunately I didn't track it somewhere. – Zack Hoffmann Jan 4, 2017 at 21:17 This settings saved my life ... thanks to Zack. They are defined in org.springframework.security.oauth2.client.token.grant.redirect.AbstractRedirectResourceDetails. – Dominik Sep 20, 2017 at 5:57 Can you provide full example of this one wtih github repo? Spent so many hours but still stuck with redirect_uri. – Keyul Jun 27, 2018 at 3:24

You may need to ensure that your application understands x-forwarded headers from your load balancer.

Putting this in my application.yml fixed my very similar problem with an application behind an AWS ELB:

server:
  tomcat:
    remote-ip-header: x-forwarded-for
    protocol-header: x-forwarded-proto

Edit: This can be simplified with the more generic configuration:

server:
  use-forward-headers: true

For Apache Tomcat use RemoteIpValve in server.xml (above AccessLogValve):

    <Valve className="org.apache.catalina.valves.RemoteIpValve" 
        protocolHeader="X-Forwarded-Proto" />

See also: https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html.

I agree with Carlos, OP, this is the best answer I've found for the latest versions of Spring Security. I'm using Spring 5.1.9.RELEASE, Spring Security 5.1.6.Release and Spring Boot 2.1.8.RELEASE. – Jason Buchanan Sep 9, 2019 at 14:18 @ImtiazShakilSiddique added info about RemoteIpValve. You should be able to use it in Tomcat 6 and above. – Nux May 11, 2020 at 14:56 Note that as of Spring Boot 2.2. you should use server.forward-headers-strategy=native instead of server.use-forward-headers, see stackoverflow.com/questions/59126518/… – Till Kuhn Jul 1, 2020 at 19:16

My answer is for people using latest spring version, as the answers suggested above didnt work for me. I am using Spring Boot 2.3.5.RELEASE.

I had a the same issue, I am using Azure AD for oauth2 authentication. My application runs behind the reverse proxy and redirect uri formed was taking http rather than https.

After reading the document https://docs.spring.io/spring-security/site/docs/5.2.x/reference/html/oauth2.html#oauth2Client-auth-code-redirect-uri , I added below line in the application.properties files and it worked for me

spring.security.oauth2.client.registration.azure.redirect-uri=https://{baseHost}{basePort}{basePath}/login/oauth2/code/azure

Since you have mentioned the use of oauth I think this will help someone to understand the flow of operation. This answer only applies if you are using a reverse proxy such as NGINX.

Cause of the problem,  

Your spring boot application is running on the server with a address simlar to http://localhost:8080 . That's what all the spring boot app know about its host. You can inspect this behavior if you check the redirect url in facebook(or other oauth client) error page. It will look something like https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture.width(250).height(250),link&redirect_url=http%3A%2F%2Flocalhost%2Flogin%2Ffacebook

See the redirect_url is wrong.

So we need to somehow tell the application that it is hosted under this address.

Quick fix

If you are only looking to fix Facebook OAuth ( Or other oAuth provider), Adding following lines to client will fix.

facebook:
  client:
     preEstablishedRedirectUri: https://yourdomain.com/
     useCurrentUri: false

But, this will only fix the issue at hand ( Also not flexible). But if you need a more concrete solution which is portable, you need to solve this at the reverse proxy.

Open your nginx configuration for the app and change it reflecting as follows.

location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Will add the user's ip to the request, some apps need this
        proxy_set_header X-Forwarded-Proto $scheme; # will forward the protocole i.e. http, https
        proxy_set_header X-Forwarded-Port $server_port; # Will forward the port 
        proxy_set_header Host $host;                    # !Important will forward the host address
        proxy_pass http://localhost:8080/;

Okay so now, nginx is sending the information which were previously hidden to the spring boot app. But yet, spring app is not using this information. To tell it to use these information add the following line to the application.yml.

server.use-forward-headers = true

If you have your reverse proxy in a different node of the same network, you may want to configure the ip of the reverse proxy server with the following. ( replace with your IP)

server.tomcat.internal-proxies=192\.65\.210\.55
I add theses two parameters to force HTTPS in redirect_uri :

preEstablishedRedirectUri: https://...
useCurrentUri: false

It works : "redirect_uri" is now using HTTPS

You have to make this change in the Spring oauth properties. If you are using separate configuration you can use OAuth2RestTemplate and by using a OAuth2ProtectedResourceDetails you can setup those properties. I did this and it works. – tn.stackoverflow Oct 4, 2018 at 9:59

you may need to use spring.oauth2.client.access-token-uri

configuration parameter changed after 1.3.0.M1

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.3.0-M1-Configuration-Changelog

0 down vote How does it handle the redirect after it authenticates. OAuth2ClientAuthenticationProcessingFilter is added by the @@EnableOAuth2Sso so I do not have a way to redirect. The default redirect is "/" (context) and again it uses http. Has anybody made this working successfully? – Paul Dec 14, 2018 at 23:52

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.