Extend Spring security OAuth2 to store additional client data - spring-security

I am using spring security OAuth2. I was wondering if I there is any easy/clean way to extend spring OAuth2 module to storing additional information associated with that client e.g, Email Id associated to the client and retrieve this in OAuth2Authentication.
I explored ClientDetailsService and AuthorizationRequest, but looks like there is no easy way to achieve this without overriding a whole bunch of classes. A quick Google search did not help either.
Has anyone else faced a similar problem? Any suggestions would be welcome. Thanks.

Spring Ouath2 provide JdbcClientDetailsService. It looks for oauth_client_details table.
You can create your own class with your own table name and column names.
<beans:bean id="clientDetails"
class="MyOwnClass">
<beans:constructor-arg ref="dataSource" /></beans:bean>
Provide the reference of above bean wherever you need client details something like this
<oauth:authorization-server
client-details-service-ref="**clientDetails**" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code disabled="true" />
<oauth:implicit />
<oauth:refresh-token disabled="true" />
<oauth:client-credentials />
<oauth:password disabled="true" />
</oauth:authorization-server>
<beans:bean id="userApprovalHandler"
class="com.mkyong.common.controller.SparklrUserApprovalHandler">
<beans:property name="approvalStore" ref="approvalStore" />
<beans:property name="clientDetailsService" ref="**clientDetails**" />
<beans:property name="requestFactory" ref="defaultOAuth2RequestFactory" />
</beans:bean>

Related

jdbc is not working in spring security

I am developing a simple struts2 login using spring security
and everything working properly.But when i use jdbc to load users and their corresponding roles,it always showing my custom invalid user page.There is no error showing and i dont know what is wrong.
My applicationcontext-security.xml
<global-method-security secured-annotations="enabled" />
<http auto-config="true">
<intercept-url pattern="/admin.action" access="ROLE_ADMIN" />
<intercept-url pattern="/user" access="ROLE_USER" />
<access-denied-handler error-page="/WEB-INF/Content/403.jsp" />
<form-login login-page="/WEB-INF/Content/login.jsp"
default-target-url="/admin.action"
always-use-default-target="true"
authentication-failure-url="/login.action?error=true"
/>
<logout logout-url="/login.action?logout=1" />
</http>
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select username,password from users where username=?"
authorities-by-username-query="select u.username, ur.authority from users u, user_roles ur where u.username = ur.username and u.username=?"
/>
</authentication-provider>
</authentication-manager>
my dataAccessContext.xml is
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/Boban"/>
<property name="username" value="root"/>
<property name="password" value="veradis"/>
</bean>
When i directly give user,password and authority it works.I searched a lot in google and found similar errors,but nothing works.I Checked the sql query and it works perfectly.I am stuck with this program.Any help will be greatly appreciated.
I believe that the query for login missing one field enabled
Try something like this:
"select username,password, enabled from users where username=?"

How to avoid repeating the string array in #Secured spring security

To secure my REST API's I am using #Secured({"ROLE_ADMIN", "ROLE_SUPERADMIN", ...some more} etc.
But I have to repeat this on every API manually. I found https://burtbeckwith.com/blog/?p=1398 for Groovy but couldn't find about how to do it in JAVA.
From my understanding I feel that I have to write a custom annotation (e.g. #MySecured("OnlyAdmins") ) which will work as a sort of Pre-Processor and will get replaced with the above #Secured annotation.
However I wanted to know if there is any better way to achieve the same? Also it would be really helpful if somebody could point me to some ready made custom annotation source code for achieving this.
Thanks in advance
To avoid this, create a parent role ALL_ADMINS, and setup spring security hierarchical roles, see the documentation for further details.
creating a role voter with the configured role hierarchy:
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
<constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<property name="hierarchy">
<value>
ROLE_ALL_ADMINS > ROLE_ADMIN
ROLE_ALL_ADMINS > ROLE_SUPERADMIN
...
</value>
</property>
</bean>
Then applying it to a custom access decision manager:
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<beans:property name="decisionVoters">
<beans:list>
<beans:bean ref="roleVoter" />
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</beans:list>
</beans:property>
</beans:bean>
and last configuring the custom access decision manager to be used by #Secured:
<global-method-security access-decision-manager-ref="accessDecisionManager">
...
</global-method-security>

Spring security oauth 2 simple example

I try to implement my own example based on official tutorial Sparklr2/Tonr2. Everything looks good but when I remove from web.xml in my Tonr2 implementation, spring security filter I have exception:
No redirect URI has been established for the current request
I can't understand what URL should I use. Here is my code, for client implementation:
<!--apply the oauth client context -->
<oauth:client id="oauth2ClientFilter" />
<!--define an oauth 2 resource for sparklr -->
<oauth:resource id="provider" type="authorization_code" client-id="client" client-secret="secret"
access-token-uri="http://localhost:8080/provider/oauth/token" user-authorization-uri="http://localhost:8080/provider/oauth/authorize" scope="read,write" />
<beans:bean id="clientController" class="com.aouth.client.ClientController">
<beans:property name="trustedClientRestTemplate">
<oauth:rest-template resource="provider" />
</beans:property>
</beans:bean>
And for provider:
<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic />
</http>
<authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<!-- The OAuth2 protected resources are separated out into their own block so we can deal with authorization and error handling
separately. This isn't mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/secured" create-session="never" access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/secured" access="ROLE_USER,SCOPE_READ" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<http-basic />
</http>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean>
<oauth:resource-server id="resourceServerFilter" resource-id="resource" token-services-ref="tokenServices" />
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails"/>
</bean>
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />
<http auto-config="true" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/test" access="ROLE_USER" />
<intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
</http>
<authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider>
<user-service>
<user name="pr" password="pr" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices" >
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="client" resource-ids="resource" authorized-grant-types="authorization_code, implicit"
authorities="ROLE_CLIENT" scope="read,write" secret="secret" />
</oauth:client-details-service>
I just want my client to work without spring security. And when I need my protected resource I want to login only on provider side.
You 2nd XML that you pasted here is the spring's XML for the oauth-provider and the protected-resource, which in your case run in the same webapp. (you can separate them, of course, if you wish).
The client (the 1st pasted-XML) is a different story. If I understand you correctly, you want your client to run without Spring's help (to be a regular webapp, and not spring-security-oauth-client webapp).
You have to understand how oAuth works: the client tries to get to a protected resource; if it does not have the access-token, it is being redirected to the oAuth-provider (that shows the login page and supplies the token). By the standard, the request for the access-token MUST contain a "redirect-uri" param, so after a successful login, the oAuth-provider knows where to redirect the client to. The oAuth client does it for you, and if you delete the "oauth client" from your web.xml, you now have to implement this by yourself.
Thanks for your answer. But I still don't understand how spring
security influences my oAuth client. And can I use for client side
spring-oauth (spring-mvc) without spring-security?
When you write this line in your XML:
< oauth:client id="oauth2ClientFilter" />
it means that you use spring-security-oauth, which is a package dedicated for oauth, built on spring-security. If you dig in, it puts a special filter (OAuth2ClientContextFilter) in the chain that handles the oAuth stuff, that are relevant for the client. One of them is sending the request with all the params ("redirect-uri" is one of them).
If you decide NOT to use spring-security-oauth, well - you will have to implement this logic by yourself...
Hope that helps!

Web App won't start after upgrading from 3.0.2 to 3.1.2

I have a working 3.0.2 applicationContext-security.xml that uses a custom authenticator
<global-method-security pre-post-annotations="disabled">
</global-method-security>
<http use-expressions="true">
<intercept-url pattern="/diagnostics/**" access="hasRole('ROLE_USER')" />
<form-login login-page="/genesis" default-target-url="/diagnostics/start-diagnostics"
authentication-failure-url="/genesis?authfailed=true"
authentication-success-handler-ref="customTargetUrlResolver"/>
<access-denied-handler error-page="/genesis?notauthorized=true"/>
<logout logout-success-url="/genesis"/>
<session-management session-authentication-error-url="/genesis">
<concurrency-control max-sessions="1" expired-url="/genesis?sessionExpired=true"/>
</session-management>
</http>
<authentication-manager>
<authentication-provider ref="genesisAuthenticator">
<jdbc-user-service data-source-ref="dataSource"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="genesisAuthenticator" class="com.blackbox.x.web.security.Authenticator"/>
<beans:bean id="customTargetUrlResolver" class="com.blackbox.x.web.security.StartPageRouter"/>
</beans:beans>
After upgrading to 3.1.2 my application will not start and I get the error message
"Configuration problem: authentication-provider element cannot have child elements when used with 'ref' attribute". I'm assuming that the problem lies with the
<jdbc-user-service data-source-ref="dataSource"/>
element where data-source-ref points to a definition in my application-context.xml file.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/genesis"/>
<property name="username" value="dbuser"/>
<property name="password" value="********"/>
What do I need to do to get this working. Dropping back to 3.0.2 is not really an option.
If you use a custom AuthenticationProvider implementation you'll have to configure it in XML in "traditional" Spring way, because <security:authentication-provider ref="yourImpl"> just points to bean which can authenticate whatever in whatever way, and don't really have to use UserDetailsService at all. In your example you tried to use jdbc-user-service which is just shortcut for creating JdbcDaoImpl bean.
So what you have to do is to assure that all genesisAuthenticator dependencies are resolved by yourself not Spring Security. That is you should either add #Autowired setUserDetailsService(UserDetailsService userDetailsService) method to your bean or configure it in XML like this (using id attribute):
<beans:bean id="genesisAuthenticator"
class="com.blackbox.x.web.security.Authenticator">
<property name="userDetailsService" ref="jdbcUserService"/>
</beans:bean>
<jdbc-user-service id="jdbcUserService" data-source-ref="dataSource" />

Creating a custom authentication with Acegi/Spring Security

I'm having trouble discovering exactly what I need to implement in order to use a custom authentication method with my web application using Spring Security. I have a Grails application with the Spring Security plugin that currently uses the standard user/password authentication with a browser form. This is working correctly.
I need to implement a mechanism alongside of this that implements a type of MAC authentication. If the HTTP request contains several parameters (e.g. a user identifier, timestamp, signature, etc.) I need to take those parameters, perform some hashing and signature/timestamp comparisons, and then authenticate the user.
I'm not 100% sure where to start with this. What Spring Security classes do I need to extend/implement? I have read the Reference Documentation and have an okay understanding of the concepts, but am not really sure if I need a Filter or Provider or Manager, or where/how exactly to create Authentication objects. I've messed around trying to extend AbstractProcessingFilter and/or implement AuthenticationProvider, but I just get caught up understanding how I make them all play nicely.
Implement a custom AuthenticationProvider which gets all your authentication information from the Authentication: getCredentials(), getDetails(), and getPrincipal().
Tie it into your Spring Security authentication mechanism using the following configuration snippet:
<bean id="myAuthenticationProvider" class="com.example.MyAuthenticationProvider">
<security:custom-authentication-provider />
</bean>
This step is optional, if you can find a suitable one from standard implementations. If not, implement a class extending the Authentication interface on which you can put your authentication parameters:
(e.g. a user identifier, timestamp, signature, etc.)
Extend a custom SpringSecurityFilter which ties the above two classes together. For example, the Filter might get the AuthenticationManager and call authenticate() using your implementation of Authentication as input.
You can extend AbstractAuthenticationProcessingFilter as a start.
You can reference UsernamePasswordAuthenticationFilter which extends AbstractAuthenticationProcessingFilter. UsernamePasswordAuthenticationFilter implements the standard Username/Password Authentication.
Configure your Spring Security to add or replace the standard AUTHENTICATION_PROCESSING_FILTER. For Spring Security Filter orders, see http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html#filter-stack
Here is a configuration snippet for how to replace it with your implementation:
<beans:bean id="myFilter" class="com.example.MyAuthenticationFilter">
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
</beans:bean>
I have recently put up a sample application that does custom authentication with Spring Security 3.
The source code is here.
More details are in this blog post.
Here is an example of securityContext.xml configuration file using custom autenticationFilter (extending AUTHENTICATION_PROCESSING_FILTER) and authenticationProvider. The user authentication data is provided by jdbc connection. Configuration is for Spring Security 2.0.x
<?xml version="1.0" encoding="UTF-8"?>
<sec:global-method-security />
<sec:http auto-config="false" realm="CUSTOM" create-session="always" servlet-api-provision="true"
entry-point-ref="authenticationProcessingFilterEntryPoint" access-denied-page="/notauthorized.xhtml"
session-fixation-protection="migrateSession">
<sec:port-mappings>
<sec:port-mapping http="80" https="443" />
</sec:port-mappings>
<sec:anonymous granted-authority="ROLE_ANONYMOUS" username="Anonymous" />
<sec:intercept-url pattern="/**" access="ROLE_ANONYMOUS, ROLE_USER" />
<sec:logout logout-url="/logoff" logout-success-url="/home.xhtml" invalidate-session="false" />
</sec:http>
<bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.xhtml" />
<property name="forceHttps" value="false" />
</bean>
<bean id="authenticationProcessingFilter" class="mypackage.CustomAuthenticationProcessingFilter">
<sec:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" />
<property name="defaultTargetUrl" value="/" />
<property name="filterProcessesUrl" value="/logon" />
<property name="authenticationFailureUrl" value="/loginError.xhtml" />
<property name="alwaysUseDefaultTargetUrl" value="false" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<jee:jndi-lookup id="securityDataSource" jndi-name="jdbc/DB_DS" />
<bean id="myUserDetailsService" class="mypackage.CustomJdbcDaoImpl">
<property name="dataSource" ref="securityDataSource" />
<property name="rolePrefix" value="ROLE_" />
</bean>
<bean id="apcAuthenticationProvider" class="mypackage.CustomDaoAuthenticationProvider">
<property name="userDetailsService" ref="myUserDetailsService" />
<sec:custom-authentication-provider />
</bean>
<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref local="apcAuthenticationProvider" />
</list>
</property>
</bean>
</beans>

Resources