Hi Arun,
We are using the 2 legged approach as part of Oauth2. We are having REST based web services and these are accessed by standalone Java clients. There is no end user here. We secured the REST services using Oauth2.Below is our configuration.
Our clients are configured using client_credentials grant in DB.
Only issue we are facing is that client_credentials does not support refresh token. So we are thinking. Otherwise this is working perfectly for us.
Hope that helps :
Code:
Service side
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:sec="http://www.springframework.org/schema/security"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- 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="/ws/claims/**" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/ws/claims/**" access="ROLE_CLIENT,SCOPE_READ" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="claimhistory" />
</bean>
<bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="claimhistory/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<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>
<authentication-manager alias="authenticationManager" 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>
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">
<constructor-arg index="0"><ref bean="dataSource"/></constructor-arg>
</bean>
<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="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
<property name="tokenServices" ref="tokenServices" />
</bean>
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter" resource-id="claimhistory" token-services-ref="tokenServices" />
<bean id="clientDetails" class="org.springframework.security.oauth2.provider.JdbcClientDetailsService">
<constructor-arg index="0"><ref bean="dataSource"/></constructor-arg>
</bean>
<mvc:annotation-driven />
<mvc:default-servlet-handler />
<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
<!--you could also wire in the expression handler up at the layer of the http filters. See https://jira.springsource.org/browse/SEC-1452 -->
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
<!--Basic application beans. -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
</map>
</property>
<property name="viewResolvers">
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</property>
<property name="defaultViews">
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="extractValueFromSingleKeyModel" value="true" />
</bean>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@sla740q1.unix.magellanhealth.com:1521/mpsappdv.magellanhealth.com"/>
<property name="username" value="liferayAppUserQ"/>
<property name="password" value="W3lc0m301"/>
</bean>
</beans>
Code:
client side :
ClientCredentialsResourceDetails resource = new ClientCredentialsResourceDetails();
resource.setAccessTokenUri(claimHistoryTokenUrl);
resource.setClientId("my-client-with-secret"); //my-client-with-registered-redirect
resource.setId("claimhistory");
resource.setScope(Arrays.asList("read"));
resource.setClientSecret("ak_secret");
//resource.setGrantType("web_server");
System.out.println("is client only -- > " + resource.isClientOnly());
OAuth2RestTemplate template2 = new OAuth2RestTemplate(resource);
OAuth2AccessToken token = template2.getAccessToken();
System.out.println("Token value ->"+token.getValue());
System.out.println("Token type ->"+token.getTokenType());
// System.out.println("refresh token -- > " + token.getRefreshToken().getValue());
// ((DefaultOAuth2AccessToken) oldToken).setExpiration(new Date(0L));
// DefaultOAuth2AccessToken oldToken = new DefaultOAuth2AccessToken("1f7bc495-6afc-4e46-8c7e-554ebfd68a0d");
// oldToken.setTokenType("bearer");
AccessTokenRequest accessTokenrequest = new DefaultAccessTokenRequest();
accessTokenrequest.setExistingToken(token);
OAuth2RestTemplate template = new OAuth2RestTemplate(resource, new DefaultOAuth2ClientContext(accessTokenrequest));
List messageConverters = new ArrayList();
messageConverters.add(new MappingJacksonHttpMessageConverter());
template.setMessageConverters(messageConverters);
if (request instanceof ClaimHistoryRequest) {
try{
return (Object)template.postForObject(claimHistoryEndpointUrl,request , ClaimHistoryResponse.class);
}catch(Exception e){
e.printStackTrace();
System.out.println(e.getMessage());
}
} else {
return (Object)template.postForObject(claimDetailsEndpointUrl,request , ClaimDetailsResponse.class);
}
return new Object() ;