Announcement Announcement Module
Collapse
No announcement yet.
Need 2-legged OAuth example Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Need 2-legged OAuth example

    Hi,

    I need a working OAuth 2-legged example either in 1.0 or 2.0.

    Thanks in advance,
    Arun.

  • #2
    Provider or consumer if OAuth 1? OAuth 2 doesn't use the terminology "2-legged" but a client-credentials grant has only 2 participants, so maybe that's what you need (sparklr2 and it's integration tests are a working example or server and client).

    Comment


    • #3
      Hi Dave,

      I have the sparklr2 and tonr2 application working in my machine.

      I just need to eliminate that "Authorize" step in the process of accessing the photos. Do u have any idea of how to do that?

      Thanks in advance,
      Arun.

      Comment


      • #4
        Your best bet is probably a UserApprovalHandler if that's all you want. But that wouldn't be 2-legged would it?

        Comment


        • #5
          Dave,

          Do you have any sample on how to add the UserApprovalHandler in OAuth2?

          Thanks & Regards,
          Arun.

          Comment


          • #6
            Sparklr2 has a custom user approval handler. Did you look there? Also see https://github.com/cloudfoundry/uaa/...oints.xml#L160.

            Comment


            • #7
              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() ;

              Comment


              • #8
                Hi akawale,

                Thanks for the reply. Your sample code really helped a lot.

                I just want to take a look at your web.xml. Could you please share it? Thanks in advance.

                Comment


                • #9
                  Hi Arun,
                  Please see below the web.xml.
                  We basically configured two servlets - one dispatcher and anather one to take our requests after the authentication is
                  done by Oauth2.
                  Code:
                  <?xml version="1.0" encoding="UTF-8"?>
                  <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
                  	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
                  	version="3.0">
                  	<display-name></display-name>
                  	  
                  	  
                  	<login-config>
                    			<auth-method>CLIENT-CERT</auth-method>
                  	</login-config>
                  	
                  	 <filter>
                      	<filter-name>ServiceContextFilter</filter-name>
                      	<filter-class>com.magellanhealth.tds.mps.base.ServiceContextFilter</filter-class>
                    	</filter>
                    	<filter-mapping>
                      	<filter-name>ServiceContextFilter</filter-name>
                      	<url-pattern>/*</url-pattern>
                    	</filter-mapping>
                  	  
                      <filter>
                  		<filter-name>springSecurityFilterChain</filter-name>
                  		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
                  	</filter>
                  
                  	<filter-mapping>
                  		<filter-name>springSecurityFilterChain</filter-name>
                  		<url-pattern>/*</url-pattern>
                  	</filter-mapping>
                  	
                   <context-param> 
                      <param-name>contextConfigLocation</param-name>
                      <param-value>classpath:appConfig.xml</param-value>
                    </context-param>
                     
                     <listener> 
                      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
                    </listener>
                    
                    
                      <servlet>
                  	    <servlet-name>spring</servlet-name>
                  	    <servlet-class>
                  	        org.springframework.web.servlet.DispatcherServlet
                  	    </servlet-class>
                  	    <init-param>
                  	        <param-name>contextConfigLocation</param-name>
                  	            <param-value>classpath:appConfig.xml</param-value>
                  	    </init-param>
                  	    <load-on-startup>1</load-on-startup>
                  	</servlet>
                  	<servlet-mapping>
                  	    <servlet-name>spring</servlet-name>
                  	    <url-pattern>/*</url-pattern>
                  	</servlet-mapping>
                  
                  	<servlet>
                  		<servlet-name>AuthorizationServlet</servlet-name>
                  		<servlet-class>
                          	org.springframework.web.context.support.HttpRequestHandlerServlet
                      	</servlet-class>
                  		<load-on-startup>15</load-on-startup>
                  	</servlet>
                   
                  
                  	<servlet-mapping>
                  		<servlet-name>AuthorizationServlet</servlet-name>
                  		<url-pattern>/ws/*</url-pattern>
                  	</servlet-mapping>
                    
                  	
                  	<welcome-file-list>
                  		<welcome-file>index.jsp</welcome-file>
                  	</welcome-file-list>
                  </web-app>

                  Comment


                  • #10
                    hi akawale,

                    Please find my web.xml below :

                    Code:
                    <?xml version="1.0" encoding="UTF-8"?>
                    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
                    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
                    	<context-param>
                    		<param-name>contextConfigLocation</param-name>
                    		<param-value>/WEB-INF/mediaOpsWSContext.xml</param-value>
                    	</context-param>
                    
                    	<context-param>
                    		<param-name>parentContextKey</param-name>
                    		<param-value>mediaservices.context</param-value>
                    	</context-param>
                    
                    	<context-param>
                    		<param-name>locatorFactorySelector</param-name>
                    		<param-value>classpath*:msBeanRefContext.xml</param-value>
                    	</context-param>
                    	<context-param>
                    		<param-name>resteasy.scan</param-name>
                    		<param-value>true</param-value>
                    	</context-param>
                    	<context-param>
                    		<param-name>resteasy.servlet.mapping.prefix</param-name>
                    		<param-value>/</param-value>
                    	</context-param>
                    
                    	<filter>
                    		<filter-name>springSecurityFilterChain</filter-name>
                    		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
                    		<init-param>
                    			<param-name>contextAttribute</param-name>
                    			<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.Resteasy</param-value>
                    		</init-param>
                    	</filter>
                    
                    	<filter-mapping>
                    		<filter-name>springSecurityFilterChain</filter-name>
                    		<url-pattern>/*</url-pattern>
                    	</filter-mapping>
                    
                    	<listener>
                    		<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
                    	</listener>	
                    
                    	<servlet>
                    		<servlet-name>Resteasy</servlet-name>
                    		<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
                    		<load-on-startup>1</load-on-startup>
                    	</servlet>
                    
                    	<servlet-mapping>
                    		<servlet-name>Resteasy</servlet-name>
                    		<url-pattern>/*</url-pattern>
                    	</servlet-mapping>
                    
                    	<listener>
                    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
                    	</listener>
                    
                    </web-app>
                    Am getting the below exception while accessing the application :

                    Code:
                    2013-02-20 04:08:56,229 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/mediaops/services].[Resteasy]] (http-166.77.177.87-8841-1) Servlet.service() for servlet Resteasy threw exception
                    
                            java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
                                    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:251)
                                    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                                    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                    at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                                    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                                    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
                                    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
                                    at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
                                    at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
                                    at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
                                    at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
                                    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                                    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
                                    at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
                                    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                                    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
                                    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
                                    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
                                    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
                                    at java.lang.Thread.run(Thread.java:619)
                    I have added the ContextLoaderListener in my web.xml, but still am getting this exception. Do u have any idea of how to resolve this. Thanks in advance.

                    Comment


                    • #11
                      You do not have the Spring dispatcher servlet in web.xml. you can refer my web.xml.

                      Comment


                      • #12
                        Hi akawale,

                        What is the "ServiceContextFilter" in your web.xml?

                        And, do you use RESTeasy?

                        Thanks,
                        Arun.

                        Comment


                        • #13
                          You can ignore ServiceContextfilter. Thats for our internal logging.
                          No we don't use RestEasy. We actually are not having the Oauth2 configuration in our actual Web service. We created a separate service which is just a servlet. It has the web.xml I have shared. This service takes the Oauth2 token request(/Oauth/token) grants token.
                          Then when the actual web service request comes, it comes to this service first. This service authorizes it then forwards it to the relevant service based on URL. This service just has a servlet to do the forwarding.
                          Our actual web service use Jersey(and NOT REST easy) API.

                          Comment


                          • #14
                            Hi akawale,

                            In your client code, there is no authentication step. How do you login to the application, before getting the access token?

                            Thanks,
                            Arun.

                            Comment

                            Working...
                            X