Spring security oauth2 wrongly using internal URL as current URI for redirection - spring

In the Spring definition of a remote resource that is protected via OAuth2 to which the client application wants access, I set use-current-uri to true, in other words, the current URI should be used as a redirect (if available). It looks like:
<oauth:resource id="myResourceId" type="authorization_code"
client-id="${clientId}" client-secret="${clientSecret}"
access-token-uri="${accessTokenUri}"
user-authorization-uri="${userAuthorizationUri}"
use-current-uri="true"
scope="myScope"
pre-established-redirect-uri="${preEstablishedRedirectUri}"/>
Now the problem is, the Spring Security OAuth2 client will pick up the current internal Tomcat URL instead of the public web application's URL. The scenario is Tomcat server sitting behind Apache server, which results in two sets of URLs:
The public web application's URL is http://example.com/users/login
The internal Tomcat URL is http://localhost:8080/myapplication/users/login
Because the redirection URL is for the authorization server (e.g., Twitter, ORCID) to use to send back the authorization code, the public web application's URL should be used, not the internal one.
By the way, I'm using the following version of spring-security-oauth2:
spring-security-oauth2-1.0.5.RELEASE
spring-core-3.1.2.RELEASE
spring-security-core-3.1.3.RELEASE
Wonder if there is a way to tell Spring to use the public URL. Thanks.

Inside your tomcat conf/server.xml's connector element , try setting your public URLs that front tomcat like this:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
proxyName="example.com"
proxyPort="443" (or whatever port you are using, same goes for scheme )
scheme="https" />
This way tomcat's internal getServerName and getServerPort methods will start giving the correct values which hopefully should create the correct URL.
You might also want to configure your webserver to route requests falling at
http://example.com/users/login to http://localhost:8080/myapplication/users/login if not already done.

Related

How to make relative redirect to Authorization Endpoint in Spring OAuth?

I configured a service with oauth2Login.
User is redirected to Authorization Endpoint - /oauth2/authorization/{registrationId} when he/she is not authorized.
I would like to customize redirection in a way that it takes into account path prefix, since application is accessible trough prefix /api/myapp/.
From the source code I can see that there is OAuth2AuthorizationRequestRedirectWebFilter during Spring Security setup and this filter is using DefaultServerRedirectStrategy which decides if location is relative or not. Moreover it uses a contextPath which is hard to set when using Spring Boot.
Unfortunately I don't know how to override default behavior to make redirect relative.
I don't need to modify contextPath. Instead I've registered ForwardedHeaderTransformer as a bean.
This transformer is able to retrieve headers set by proxy (X-Forwarded-Prefix) and sets context path for request correctly.

Where is RESTful API parameter URL-decoded?

I have a Spring-based RESTful API which is deployed to a Tomcat server. When I call this API like below (value of "para" has been URL-encoded) and debug it, value of "para" in controller method is "aaa bbb" which has already been URL-decoded.
GET http://MY-TOMCAT-SERVER/SOME-PATH?para=aaa%20bbb
However, when I run a SpringBoot-based local Test Automation case (not deployed anywhere) to test the same API, the value of "para" in controller method hasn't been URL-decoded.
Question is, what is the difference between the two scenarios and where is "para" URL-decoded in the first scenario?
Hopefully I can give you a hint for the first part of your question:
The Apache Tomcat server.xml contains an tag Connector, this tag can have an optional attribute URIEncoding. Example:
<Connector connectionTimeout="20000"
port="8080"
protocol="HTTP/1.1"
redirectPort="8443"
URIEncoding="UTF-8" />
So I think that Tomcat is responsible for the URI encoding. But I do not know how this is activated in an Embedded-Spring-Boot-Tomcat.
#See: How does URIEncoding = 'UTF-8' work?
#See: Apache Tomcat 8 Configuration Reference / The HTTP Connector

Http post forwarding on tomcat level to different domain

I have two set of server on different domains using tomcat .
Now I want to forward http post call from one server to another preserving the payload in http entity throughout.
Problem is I donot want to change code and want this to be done on tomcat level anymeans.
I currently is trying to use URLrewriteFilter but not getting through.
any suggestions ?
URLrewriteFilter may help. You can define a proxy type for element.
The request will be proxied to the full url specified. commons-http
and commons-codec must both be in the classpath to use this feature.
Sample:
<rule>
<name>A Rule</name>
<from>^/something$</from>
<to type="proxy">http://anotherserver.com/something</to>
</rule>

Disable jsessionid via http header (cookie) in Tomcat 7

I'm looking to disable jsessionid from being used in the https headers.
Is there a way to turn this off or disable this being set as a cookie in tomcat 7?
I either want the jsessionid to arrive embedded into a GET method url name value pairs or to be part of a POST request name value pairs.
I know all the advantages and disadvantages of using cookie based sessioning and url rewriting but I have specific needs for specific impl of restful web services.
I need tomcat 7 to accept jsessionid without using the http header: jsessionid.
Thanks.
UPDATE:
so I looked around some more and found this which is implemented using the web.xml conf.
However the following doesn't seem to work with Tomcat 7.
<session-config>
<tracking-mode>URL</tracking-mode>
</session-config>
is it a case of TC7 not fully implementing the servlet 3.0 spec?
The web.xml setting works for me with Tomcat 7.0.20.
Log and check the effective (and maybe the default) session tracking modes:
logger.info("default STM: {}" , servletContext.getDefaultSessionTrackingModes());
logger.info("effective STM: {}" , servletContext.getEffectiveSessionTrackingModes());
Maybe your app override somewhere in the code the session tracking modes. An example:
final Set<SessionTrackingMode> trackingModes =
Collections.singleton(SessionTrackingMode.COOKIE);
servletContext.setSessionTrackingModes(trackingModes);
Check ServletContext.setSessionTrackingModes() calls in your code.
It's also possible to set default session tracking modes in the Tomcat's context settings but I found that web.xml settings override them.

Tomcat/Spring SSL configuration

I'm trying to configure my Spring application to use an SSL certificate I purchased from a CA. I followed the directions for the Tomcat 6.0 configuration and have imported the key into my Tomcat keystore and uncommented the SSL connector in the server.xml. When I start Tomcat, I see the connector start on port 8443 in the Tomcat logs, but when I go to https://example.com:8443 or http: //example.com:8443 or https: //example.com (without the spaces - I don't have the reputation to post links), it times out. What other configuration do I need to do to enable SSL for my Spring application. Do I have to change the application configuration?
I'd also like to only have some URLs over SSL (login, edit profile, etc.). How can I allow this in the Spring configuration? If I have to have all URLs accessible over SSL, that would be ok, but not desirable. I haven't found any tutorials that are Spring specific.
What you'll need to do is to edit your server.xml file to enable ssl. Here's Tomcat's guide, please check it out:
http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html
In order to programmatically know if a request has arrived through port 80 or 443, you need to inspect the value returned by request.isSecure().
To secure URLs altogether, I'd recommend using a Filter.
I don't remember how all of this is handled by Spring, but I don't think you'll have any problems to obtain the request object.
Hope that helps.
After you've configured Tomcat as per the document cited by #mschonaker, he simplest thing is to define the action in the j_security_check and edit profile forms, etc, specify the https: protocol, e.g. in a Facelet, https://#{request.serverName}:8443#{request.contextPath}/j_security_check. Then when the user hits the login button, the form POSTs via HTTPS, so they are secure.
This leaves you in HTTPS for the rest of the session: to get back to HTTP but still stay in the same session, just provide a link to a fully-specified HTTP url, e.g. in a Facelet, http://#{request.serverName}:8443#{request.contextPath}/some link.
If you have other pages you want secured when read, define appropriate security-constraint, user-data-constraint, and transport-guarantee CONFIDENTIAL elements for them in web.xml.
about the second point
I'd also like to only have some URLs over SSL (login, edit profile, etc.). ???
you could determine it by modify configration in web.xml
<security-constraint>
<web-resource-collection>
<web-resource-name>securedapp</web-resource-name>
<!-- <url-pattern>/*</url-pattern> --> <!--all pages-->
<url-pattern>/yourapp/login</url-pattern>
<url-pattern>/yourapp/edit</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
hope that help you

Resources