Many thanks for this info, Erik. I'll also take a note to add to docs, all great stuff.
Cheers Dan On 19 July 2016 at 11:42, Erik de Hair <[email protected]> wrote: > > On 07/19/2016 12:20 PM, Dan Haywood wrote: > >> Willie, >> >> thanks very much for taking the time to document all this; great to know >> it's doable. >> >> It *is* in fact possible to add additional endpoints to the RO viewer; you >> need to subclass RestfulObjectsApplication [1] to add your additional >> endpoints and then to register in web.xml [2] >> > Our application uses this approach to make it easier to configure > firewalls to access certain paths on the web server by different parties > and because we use xml webservices of suppliers that deliver xml-messages > to our application (because they dictate that). > > We added a servlet(mapping) to web.xml > > <servlet> > <servlet-name>RestfulObjectsWebServiceDispatcher</servlet-name> > > <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> > <init-param> > <param-name>resteasy.servlet.mapping.prefix</param-name> > <param-value>/ws/</param-value> > </init-param> > <!-- used by RestEasy to determine the JAX-RS resources and other > related > configuration --> > <init-param> > <param-name>javax.ws.rs.Application</param-name> > <param-value>webapp.PortalRestfulObjectsApplication</param-value> > </init-param> > </servlet> > ... > <servlet-mapping> > <servlet-name>RestfulObjectsWebServiceDispatcher</servlet-name> > <url-pattern>/ws/*</url-pattern> > </servlet-mapping> > > The implementation of webapp.PortalRestfulObjectsApplication: > > public class PortalRestfulObjectsApplication extends > AbstractJaxRsApplication { > > public PortalRestfulObjectsApplication() { > addSingleton(new RestfulObjectsApplicationExceptionMapper()); > addSingleton(new RuntimeExceptionMapper()); > // add services > addClass(AccessAvailabilityService.class); > addClass(PortingXSService.class); > } > } > > But I believe we had a problem starting multiple RestEasy applications and > I think we had to add a filter to the web application to make sure they > both start. > > public class ResteasyCleanupFilter implements Filter { > private FilterConfig config; > > @Override > public void init(FilterConfig filterConfig) throws ServletException { > this.config = filterConfig; > } > > @Override > public void doFilter(ServletRequest request, ServletResponse response, > FilterChain chain) throws IOException, ServletException { > config.getServletContext().setAttribute(ResteasyProviderFactory.class.getName(), > null); > config.getServletContext().setAttribute(Dispatcher.class.getName(), null); > chain.doFilter(request, response); > } > > @Override > public void destroy() { > // TODO Auto-generated method stub > } > } > > filter-config in web.xml > > <filter> > <filter-name>CleanupFilter</filter-name> > <filter-class>webapp.restful.ResteasyCleanupFilter</filter-class> > </filter> > <filter-mapping> > <filter-name>CleanupFilter</filter-name> > <url-pattern>/*</url-pattern> > </filter-mapping> > > Part of implementation of PortingXSService.class (in this case it's a xml > web service): > > @Path("portingxs") > public class PortingXSService extends AbstractIsisSessionTemplate { > @Context > HttpHeaders httpHeaders; > @Context > UriInfo uriInfo; > @Context > Request request; > @Context > HttpServletRequest httpServletRequest; > @Context > HttpServletResponse httpServletResponse; > @Context > SecurityContext securityContext; > > @POST > @Path("/") > @Consumes(MediaType.TEXT_XML) > @Produces({ MediaType.TEXT_XML }) > public Response receive(final String input) { > final ObjectAdapter serviceAdapter = > getServiceAdapter("nl.pocos.portingxs.PortingXSService"); > nl.pocos.portingxs.PortingXSService service = > (nl.pocos.portingxs.PortingXSService) serviceAdapter.getObject(); > Object response = ...; > ResponseBuilder rb = Response.status(200).entity(response); > return rb.build(); > } > > protected ObjectAdapter getServiceAdapter(final String serviceId) { > final List<ObjectAdapter> serviceAdapters = > getPersistenceSession().getServices(); > for (final ObjectAdapter serviceAdapter : serviceAdapters) { > final Object servicePojo = serviceAdapter.getObject(); > final String id = ServiceUtil.id(servicePojo); > if (serviceId.equals(id)) { > return serviceAdapter; > } > } > throw > RestfulObjectsApplicationException.createWithMessage(HttpStatusCode.NOT_FOUND, > "Could not locate service '%s'", serviceId); > } > } > >> >> I'll take a note to add this detail into the "ro viewer" guide [3], and >> also to add your longer recipe as to how oauth can be added into the >> "beyond the basics" guide [4] >> >> Or, if you/anyone else has the time, PRs on docs gratefully received! >> >> Thx again >> Dan >> >> >> [1] >> >> https://github.com/apache/isis/blob/master/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplication.java#L36 >> [2] >> >> https://github.com/apache/isis/blob/master/example/application/simpleapp/webapp/src/main/webapp/WEB-INF/web.xml#L272 >> [3] >> >> https://github.com/apache/isis/blob/master/adocs/documentation/src/main/asciidoc/guides/ugvro.adoc >> [4] >> >> https://github.com/apache/isis/blob/master/adocs/documentation/src/main/asciidoc/guides/ugbtb.adoc >> >> On 28 June 2016 at 08:44, Willie Loyd Tandingan <[email protected]> >> wrote: >> >> Hi Pedro and Dan, >>> >>> I've already opened the topic on open-sourcing the OAuth2 module we've >>> implemented but I don't think it can be done sooner. >>> >>> What we did was basically find an implementation of OAuth2 and integrate >>> it with Apache Isis. There are some suggested in [1] but are not well >>> maintained. I have considered replacing Shiro with Spring Security but >>> thought that it would take too much effort and time. >>> >>> In the end, we also had a hard time creating another JAX-RS application >>> since resteasy used by RO viewer unfortunately doesn't support multiple >>> applications. We wanted the OAuth2 module to be a detachable module on >>> top >>> of RO while maintaining no modifications to RO code, and with no changes >>> to >>> the existing wicket viewer. Due to these requirements, we had decided to >>> use Restlet with its oauth extension, and integrated it with Shiro, RO, >>> and >>> Apache Isis. This also allowed us to create endpoints outside of RO. At >>> the >>> moment, we are needing only the password grant flow so the tokens are >>> actually persisted but the client manager is in-memory. >>> >>> Basically we did the following to integrate Restlet with RO and Apache >>> Isis: >>> >>> 1. Implement org.restlet.ext.oauth.internal.Token as domain object. >>> 2. Implement org.restlet.ext.oauth.internal.TokenManager as domain >>> service. >>> 3. Implement org.restlet.ext.oauth.internal.Client. We implemented this >>> in-memory. >>> 4. Setup the Restlet OAuth2 token endpoint using the implementations >>> above. Note they must be running under Isis context. We referred to the >>> the >>> security addon for integration patterns, and used similar techniques e.g. >>> IsisContext to open session, execute closures using transaction manager, >>> and close session. >>> 5. Create transaction filter for this endpoint. >>> >>> Above will implement token generation, verification, and revocation. For >>> integration with Shiro: >>> >>> 6. Implement org.restlet.ext.oauth.internal.ResourceOwnerManager. This >>> creates wraps the username and password given for password grant flow in >>> a >>> AuthenticationRequestPassword, and passes it to Apache Isis >>> AuthenticationManager. >>> 7. Create implementations of AuthenticationRequestToken (we extended >>> AuthenticationRequestPassword) and AuthenticationToken. This shall >>> support >>> token authentications while still maintaining username/password >>> authentications (used in wicket and RO basic auth; since we still need to >>> support both for prototyping and development). >>> 8. Implement >>> org.apache.isis.core.runtime.authentication.standard.Authenticator, and >>> org.apache.isis.core.runtime.authorization.standard.Authorizer. We >>> extended >>> ShiroAuthenticatorOrAuthorizor to support token authentications. >>> 9. Extend IsisModuleSecurityRealm to support getting authentication info >>> for OAuth2 tokens. We had our own additions here since we need to support >>> some forms of decoupled authentication vetos from other modules e.g. if >>> tenant of the ApplicationUser is disabled then disallow login, password >>> lockout policies, etc. >>> 10. Extend AuthorizationManagerStandardInstallerAbstract and create the >>> new authorizer. >>> 11. Create an AuthenticationSessionStrategy supported token >>> authentication >>> to be used in RO. Here, we parse the token from the HTTP header, create >>> AuthenticationRequestToken, and pass to the Apache Isis >>> AuthenticationManager. >>> >>> To use in your app: >>> >>> 12. In your AppManifest, return the installer class name created in #10 >>> for getAuthenticationMechanism and getAuthorizationMechanism. >>> 13. In shiro.ini, set securityManager.realms to the security realm in #9 >>> 14. In web.xml, for the IsisSessionFilterForRestfulObjects, use the >>> authentication session strategy created in 11 for the >>> authenticationSessionStrategy init param. We also set whenNoSession to >>> continue since we needed to provide different error messages on >>> authentication failures by letting AuthenticationException propagate up >>> to >>> the authentication session strategy, and prettify the messages through >>> another filter. >>> 15. In web.xml, setup the Restlet servlet and the transaction filter in >>> #5. >>> >>> >>> I hope above makes sense. This was implemented a year ago and it's >>> already >>> a bit blurry to remember everything. I would advise to observe and study >>> the authentication flow from viewer to the authentication realms, as well >>> as the security addon. This helps in determining integration or >>> customization points to adhere to your project's requirements. >>> >>> Best regards, >>> Willie >>> >>> [1] https://issues.apache.org/jira/browse/SHIRO-119 >>> >>> On Tue, Jun 28, 2016 at 5:35 AM, Dan Haywood < >>> [email protected] >>> >>>> wrote: >>>> Hi Pedro, >>>> Apache Isis doesn't ship with oauth out of the box, but I recall Willie >>>> mentioning in passing [1] that they had extended Isis in this direction. >>>> >>>> @Willie, would you be able to share any code around this? >>>> >>>> Thx >>>> Dan >>>> >>>> http://markmail.org/message/ia76ut3mwuppdqow >>>> >>>> On 27 June 2016 at 15:18, Pedro Alba <[email protected]> wrote: >>>> >>>> Hello Dan. >>>>> >>>>> Dan, I have a question, I require implement OAuth authentication >>>>> services to the rest exposing apache isis; how I can configure apache >>>>> isis >>>>> authentication OAUTH? >>>>> >>>>> Thanks. >>>>> >>>>> [image: Logo] >>>>> >>>>> *Pedro Antonio Alba * >>>>> *Senior Development Analyst* >>>>> Tel: (57) 1 703 17 77 >>>>> Cel: (57) 301 3379810 >>>>> E-mail: [email protected] >>>>> Calle 93 # 19b - 66 Ofc 202 >>>>> Bogotá D.C., Colombia >>>>> www.ticxar.com >>>>> >>>>> >>>>> >>>>> [image: facebook] >>>>> <http://www.facebook.com/pages/Ticxar/446503822192581> [image: >>>>> twitter] >>>>> <http://twitter.com/ticxar> [image: linkedIn] >>>>> <http://www.linkedin.com/company/ticxar> >>>>> >>>>> >>>> >
