OAuth2 offers a clear differentiation between token grants and token types. Grant is what Access Token service will verify before issuing a token, and the best thing about it is that the same code path is used irrespectively of whatever grant or token is used.
OAuth2 mentions simple bearer tokens as default token types, but of course the bearer is not the only token type possible.
Eran Hammer-Lahav wrote a MAC Access Authentication draft which introduces a MAC authentication scheme and describes how it can be used in OAuth2.
OAuth2 experts are considering whether this effort has to be completed or not. I'd like to encourage those who are interested to check OAuth2 mail archives for different opinions expressed regarding the MAC scheme.
Here is my opinion for whatever it is worth:
- What is important is that OAuth2 offers a pluggable mechanism for different token types so I think users should be encouraged to experiment with new token types, MAC in this case, and see if it makes the flows more secure, and 'contribute' to the idea of completing the effort from Eran by talking about possible issues or advantages of this scheme (such as: is it simpler to operate than tokens like JWT, or is it a reasonable alternative to JWT, etc) - remember, it is still the same code path for client and server applications, only a different token type.
- Having it completed will encourage OAuth1.0 users migrate to OAuth2.0, because OAuth2.0 with MAC is a much simpler version of OAuth1.0 - MAC scheme offers a simple holder-of-key support and combined with HTTPS it makes the exchanges between clients and OAuth2 services more secure.
- It will be a good idea to complete the effort any way, some implementers will ignore it but some will like.
Sasi M. has contributed the initial MAC Token implementation to Apache CXF, thanks! The documentation is available here. Please try this token type in the applications, it is really easy to work with. Also, we'd be open to contributing the MAC-specific code to a dedicated 3rd party module if it will be useful to have the one - the details can be discussed at the CXF dev list. That said - it is just a couple of utility classes that are needed to get a MAC token created and validated. Sasi also provided a patch for a MAC nonce validator - this is not at the trunk yet but will make it there in time.
Enjoy!
Friday, September 21, 2012
Sunday, August 12, 2012
OAuth2 Demo in Talend ESB
Talend ESB ships many interesting, advanced examples demonstrating CXF and Camel in action. The demos attempt to show something interesting, something that one may try to do in the production.
JAX-RS OAuth2 demo has been evolving as a POC demo with the main goal to stress CXF OAuth2 services and make sure that they can cope with what one might want to consider as a medium complexity OAuth2 deployment.
The demo shows 4 parties cooperating with or depending on each other, where Social.com service offers the registered users an option to reserve a table at the favorite restaurant with the help of Restaurant Reservations service (with the latter depending on its own partner). A classical 3-leg OAuth flow (Authorization Code Flow in OAuth2) is demonstrated with most of the demo depending on CXF alone to do most of the work (OAuth2, Presentations, etc).
The end user (individual Social.com resource owner) can approve or disapprove a client (Restaurant Reservations) request to read and possibly update the user's calendar. The demo can be run as a simple OAuth2 demo with all the endpoints running within the same container or as an advanced demo showing how a user can interact with the application supported by many application containers, with the SAML SSO feature introduced to improve the user experience - this advanced option will be covered in detail in one of the future posts.
Please check this presentation I did at JAX-2012 in Mainz for more information.
I'd like to encourage users to try the demo, provide the feedback and git pull requests :-)
Enjoy.
JAX-RS OAuth2 demo has been evolving as a POC demo with the main goal to stress CXF OAuth2 services and make sure that they can cope with what one might want to consider as a medium complexity OAuth2 deployment.
The demo shows 4 parties cooperating with or depending on each other, where Social.com service offers the registered users an option to reserve a table at the favorite restaurant with the help of Restaurant Reservations service (with the latter depending on its own partner). A classical 3-leg OAuth flow (Authorization Code Flow in OAuth2) is demonstrated with most of the demo depending on CXF alone to do most of the work (OAuth2, Presentations, etc).
The end user (individual Social.com resource owner) can approve or disapprove a client (Restaurant Reservations) request to read and possibly update the user's calendar. The demo can be run as a simple OAuth2 demo with all the endpoints running within the same container or as an advanced demo showing how a user can interact with the application supported by many application containers, with the SAML SSO feature introduced to improve the user experience - this advanced option will be covered in detail in one of the future posts.
Please check this presentation I did at JAX-2012 in Mainz for more information.
I'd like to encourage users to try the demo, provide the feedback and git pull requests :-)
Enjoy.
Thursday, August 2, 2012
Master Kerberos Security with Apache CXF
Kerberos is a well-known security protocol, originally developed at MIT and has been a major authentication protocol on Windows.
Why would you want to learn about or experiment with Kerberos today, when developing web services ?
One may want to do it if we have a web service which needs to expose the information available from the internal Kerberos-protected store or when a Single Sign-On service needs to use Kerberos servers to keep the principal details or when Kerberos is deemed to be the best authentication protocol which can protect the given complex application exposed as a web service.
The decision by Hadoop developers to support Kerberos will undoubtedly make it more important for developers to understand what Kerberos is about, due to the fact the Big Data is becoming so important these days.
In Apache CXF, Kerberos has been supported on a number of levels for a while. Colm has published a two-part series about the way WS-Security Kerberos is supported and tested in CXF, and Christian has implemented a client-side support for the HTTP Negotiate authorization scheme.
Starting from CXF 2.6.2 (to be released soon), the JAX-RS frontend offers an additional server and client side support for making it very easy to support the Kerberos authentication for RS endpoints and clients.
After installing Kerberos packages, the next thing you can do is to run JAXRSKerberosBookTest or add server and/or client Kerberos handlers to your own application as documented at the wiki and see what actually happens.
Have you been thinking of getting started with Kerberos for Web Services ?
Do it today with Apache CXF :-)
Why would you want to learn about or experiment with Kerberos today, when developing web services ?
One may want to do it if we have a web service which needs to expose the information available from the internal Kerberos-protected store or when a Single Sign-On service needs to use Kerberos servers to keep the principal details or when Kerberos is deemed to be the best authentication protocol which can protect the given complex application exposed as a web service.
The decision by Hadoop developers to support Kerberos will undoubtedly make it more important for developers to understand what Kerberos is about, due to the fact the Big Data is becoming so important these days.
In Apache CXF, Kerberos has been supported on a number of levels for a while. Colm has published a two-part series about the way WS-Security Kerberos is supported and tested in CXF, and Christian has implemented a client-side support for the HTTP Negotiate authorization scheme.
Starting from CXF 2.6.2 (to be released soon), the JAX-RS frontend offers an additional server and client side support for making it very easy to support the Kerberos authentication for RS endpoints and clients.
After installing Kerberos packages, the next thing you can do is to run JAXRSKerberosBookTest or add server and/or client Kerberos handlers to your own application as documented at the wiki and see what actually happens.
Have you been thinking of getting started with Kerberos for Web Services ?
Do it today with Apache CXF :-)
Friday, July 27, 2012
Jettison 1.3.2 is out
Jettison 1.3.2 has been released this week, please check the Download page.
Those who try to customize the way Jettison works should find it easier to override various Jettison classes, for example, in CXF I've been able to remove about 50 lines of code I had to copy earlier on to get large Jettison sequences optionally restricted.
Jettison will no longer require a namespace map set up for the serialization to work, in cases when it is not configured to ignore namespaces, as I moved a fix provided by Benson from CXF to Jettison.
A number of minor performance enhancements have also been implemented thanks to the proposals from Fabian Lange.
During the next few interactions we will continue minimizing a number of outstanding issues, however I'd also like to encourage the community to provide patches - they will get an immediate attention during the release, as it's been the case during the last few releases. I haven't resolved one issue with the available patch to do with treating XML attributes as elements, in CXF we can manage it by providing a custom XML writer, so I needed more time on investigating if that issue can be resolved at the current Jettison implementation level effectively or not.
At some point in the future an optional streaming support will have to be introduced, either on read or write sides, even if certain restrictions will have to be there.
In meantime, please keep stressing Jettison and provide the patches :-)
Those who try to customize the way Jettison works should find it easier to override various Jettison classes, for example, in CXF I've been able to remove about 50 lines of code I had to copy earlier on to get large Jettison sequences optionally restricted.
Jettison will no longer require a namespace map set up for the serialization to work, in cases when it is not configured to ignore namespaces, as I moved a fix provided by Benson from CXF to Jettison.
A number of minor performance enhancements have also been implemented thanks to the proposals from Fabian Lange.
During the next few interactions we will continue minimizing a number of outstanding issues, however I'd also like to encourage the community to provide patches - they will get an immediate attention during the release, as it's been the case during the last few releases. I haven't resolved one issue with the available patch to do with treating XML attributes as elements, in CXF we can manage it by providing a custom XML writer, so I needed more time on investigating if that issue can be resolved at the current Jettison implementation level effectively or not.
At some point in the future an optional streaming support will have to be introduced, either on read or write sides, even if certain restrictions will have to be there.
In meantime, please keep stressing Jettison and provide the patches :-)
Thursday, July 19, 2012
CXF Log Browser Demo
A Log Browser demo has been available in the CXF distributions for more than a year now. This demo is based on the brilliant contribution from Thomasz Opanovicz done as part of his GSOC project.
What I would like to do is explain what exactly the CXF Log Browser can do right now, and suggest some ideas on how it can be enhanced.
At the moment, the browser can be used to poll the Atom-enabled management endpoints and display the available log entries, this can be done per every CXF service, JAX-WS or JAX-RS one. The Atom endpoints can be set up as described in this section and shown in the demo. Have a look at this image on how the browser can show the log entries, I think it is quite cool. Note the entries are paged, example, one can go to the next, previous, first or last pages, from the current page.
At the moment the browser polls every time the "refresh" button is pressed - this is one minor thing that can be customized further, example, a browser can be asked to poll every 60 seconds.
The browser offers an option to restrict which log entries are displayed by letting users to set FIQL search queries.
Typically, the Atom endpoint (which handles the browser queries) captures the log events, transforms them to Atom feeds and keeps them in memory or overflows to a registered ReadWriteLogStorage if needed but what is interesting it can also be configured from the start to read the log entries from the existing log files.
For example, it can be configured to check the directory where Karaf gets the log files created. CXF offers a file-based ReadableLogStorage interface implementation which can check the existing log files matching a given naming pattern, figure out which log file is newer or older and get the log entries in whatever format is used to format them using the simple configuration involving no regular expressions at all. For example, have a look at this test which works with the log files available here as well as this configuration file (check the bean with id "storage3").
All of it needs to be more extensively tested but Log Browser is already offering a fairly involved support for working with the available log entries.
However, quite a few enhancements can be done which can make it more useful and eventually turn the browser into a management console of its own.
One obvious thing which is missing is the ability to capture events immediately, with a browser acting as a receiver. For example, it would be good to get Atom push endpoints sending the events to it too. Implementing an enhancement like this one would very likely lead to Web Sockets supported in CXF. The browser would be configured to support either push or pull style on the startup or perhaps it would keep the pull style by default and get the real-time events displayed in the running line at the bottom of the window.
The browser can also offer an option to get the log files from the selected location downloaded to the local disk.
We can also have at least two more tabs available. One would show the JMX statistics related to CXF, another one would show the message exchange details.
I'd like to encourage users to try the demo, and consider helping us with enhancing the browser further.
What I would like to do is explain what exactly the CXF Log Browser can do right now, and suggest some ideas on how it can be enhanced.
At the moment, the browser can be used to poll the Atom-enabled management endpoints and display the available log entries, this can be done per every CXF service, JAX-WS or JAX-RS one. The Atom endpoints can be set up as described in this section and shown in the demo. Have a look at this image on how the browser can show the log entries, I think it is quite cool. Note the entries are paged, example, one can go to the next, previous, first or last pages, from the current page.
At the moment the browser polls every time the "refresh" button is pressed - this is one minor thing that can be customized further, example, a browser can be asked to poll every 60 seconds.
The browser offers an option to restrict which log entries are displayed by letting users to set FIQL search queries.
Typically, the Atom endpoint (which handles the browser queries) captures the log events, transforms them to Atom feeds and keeps them in memory or overflows to a registered ReadWriteLogStorage if needed but what is interesting it can also be configured from the start to read the log entries from the existing log files.
For example, it can be configured to check the directory where Karaf gets the log files created. CXF offers a file-based ReadableLogStorage interface implementation which can check the existing log files matching a given naming pattern, figure out which log file is newer or older and get the log entries in whatever format is used to format them using the simple configuration involving no regular expressions at all. For example, have a look at this test which works with the log files available here as well as this configuration file (check the bean with id "storage3").
All of it needs to be more extensively tested but Log Browser is already offering a fairly involved support for working with the available log entries.
However, quite a few enhancements can be done which can make it more useful and eventually turn the browser into a management console of its own.
One obvious thing which is missing is the ability to capture events immediately, with a browser acting as a receiver. For example, it would be good to get Atom push endpoints sending the events to it too. Implementing an enhancement like this one would very likely lead to Web Sockets supported in CXF. The browser would be configured to support either push or pull style on the startup or perhaps it would keep the pull style by default and get the real-time events displayed in the running line at the bottom of the window.
The browser can also offer an option to get the log files from the selected location downloaded to the local disk.
We can also have at least two more tabs available. One would show the JMX statistics related to CXF, another one would show the message exchange details.
I'd like to encourage users to try the demo, and consider helping us with enhancing the browser further.
Advanced queries involving multiple entities
As I've mentioned a number of times, FIQL can help with expressing the advanced search conditions in a compact and easy to understand syntax.
The queries like "find all the books published before a given date" are very easy to type in FIQL and extending this query with a restriction like "and having the page count between 80 and 100 pages or less than 20" is quite straightforward too, manually, or with the help of the client FIQL builder.
However, what if one would like to do a query involving multiple entities, for example, "find the library in a preferred location where all the books published before a given date and written by more than 2 authors are available" ? Or imagine or more interesting query if you'd like.
This bit, "where all the books published before a given date and written by more than 2 authors" is an easy one to support with the CXF search extension. The question is, how to structure the advanced query such that Book entities matching the arbitrary complex query are selected first and then a Library entity is checked per every Book on whether it matches its own selection criteria or not.
Another question is how to express the requirement that it is actually "the list of books", "published before a given date and written by more than 2 authors and available in one of the libraries in a preferred location", that has to be returned to a user.
As you can see, there are at least two main requirements to deal with. First one is how to let users choose which entity (among a number of entities being matched) is actually returned which affects the response representation. Second one is how to do an advanced query involving multiple entities at the level of the JAX-RS application handling such a query.
The good news is that the first requirement can be easily managed with the help of URI path and/or query components. For example, an expression like "/books[date=le=2012-02-11]/library" can be used to find all the libraries having the matching books, and the one like "/library(dist=lt=10;dist=gt=5)/books(date=le=2012-02-11)" can get all the books matching a given search criteria available in a library within a 10 km range from some well-known location (such as the city center) but not closer than 5 (given that the parking is not free within a 5 km range).
It is really up to the designer of the service how to get the actual expressions captured, which characters to use to mark them, example "[" and "]", "(" and ")" or ";" and how to support the selective retrieval of the entities involved in the multi-entity search. See this section for more examples.
Yet another good news is that a complex multi-entity query can be managed pretty easily at the JAX-RS resource level, see this section for a number of options on how it might be done. Note how multiple FIQL expressions can be handled.
What is mentioned there is that it can be more optimal to get say JPA to execute a JOIN like query at a database level in one go as opposed to getting it to find a list of entities matching the first FIQL expression, then doing the follow-up in-memory match against the selected entities.
Right now CXF can not automate the process of creating a JPA TypedQuery or SQL expression which can 'span' the multiple entities - this is the next task, and in meantime please experiment with the demonstrated approach and see how it fares against the one involving the composite JOIN-like queries. Alternatively, introspect the captured search conditions as shown in this section and build a composite query in the code.
Please also have a look at the OData4J project and check how the advanced queries can be managed there.
Finally, I'd like to answer on the following question: why one would worry about offering such a search interface to users, would it not be simpler to offer a Google-like search interface where one enters a few words and gets the list of matching data pages ? I think that when one creates a service for exposing the data with the known properties and relationships, the opportunity is there to offer an optimized search engine for users to get the customized search experience.
The queries like "find all the books published before a given date" are very easy to type in FIQL and extending this query with a restriction like "and having the page count between 80 and 100 pages or less than 20" is quite straightforward too, manually, or with the help of the client FIQL builder.
However, what if one would like to do a query involving multiple entities, for example, "find the library in a preferred location where all the books published before a given date and written by more than 2 authors are available" ? Or imagine or more interesting query if you'd like.
This bit, "where all the books published before a given date and written by more than 2 authors" is an easy one to support with the CXF search extension. The question is, how to structure the advanced query such that Book entities matching the arbitrary complex query are selected first and then a Library entity is checked per every Book on whether it matches its own selection criteria or not.
Another question is how to express the requirement that it is actually "the list of books", "published before a given date and written by more than 2 authors and available in one of the libraries in a preferred location", that has to be returned to a user.
As you can see, there are at least two main requirements to deal with. First one is how to let users choose which entity (among a number of entities being matched) is actually returned which affects the response representation. Second one is how to do an advanced query involving multiple entities at the level of the JAX-RS application handling such a query.
The good news is that the first requirement can be easily managed with the help of URI path and/or query components. For example, an expression like "/books[date=le=2012-02-11]/library" can be used to find all the libraries having the matching books, and the one like "/library(dist=lt=10;dist=gt=5)/books(date=le=2012-02-11)" can get all the books matching a given search criteria available in a library within a 10 km range from some well-known location (such as the city center) but not closer than 5 (given that the parking is not free within a 5 km range).
It is really up to the designer of the service how to get the actual expressions captured, which characters to use to mark them, example "[" and "]", "(" and ")" or ";" and how to support the selective retrieval of the entities involved in the multi-entity search. See this section for more examples.
Yet another good news is that a complex multi-entity query can be managed pretty easily at the JAX-RS resource level, see this section for a number of options on how it might be done. Note how multiple FIQL expressions can be handled.
What is mentioned there is that it can be more optimal to get say JPA to execute a JOIN like query at a database level in one go as opposed to getting it to find a list of entities matching the first FIQL expression, then doing the follow-up in-memory match against the selected entities.
Right now CXF can not automate the process of creating a JPA TypedQuery or SQL expression which can 'span' the multiple entities - this is the next task, and in meantime please experiment with the demonstrated approach and see how it fares against the one involving the composite JOIN-like queries. Alternatively, introspect the captured search conditions as shown in this section and build a composite query in the code.
Please also have a look at the OData4J project and check how the advanced queries can be managed there.
Finally, I'd like to answer on the following question: why one would worry about offering such a search interface to users, would it not be simpler to offer a Google-like search interface where one enters a few words and gets the list of matching data pages ? I think that when one creates a service for exposing the data with the known properties and relationships, the opportunity is there to offer an optimized search engine for users to get the customized search experience.
Tuesday, July 10, 2012
JMS Transport support for CXF JAX-RS clients
I blogged about the support for JMS by CXF JAX-RS endpoints two years ago.
The main reason behind making the JAX-RS frontend (associated by most users with supporting HTTP-based communications) JMS-aware was to do with getting the most from the 'investment' made into implementing the RESTful services on top of CXF JAX-RS.
If one has the resource code relying on the JAX-RS runtime to make the inbound data delivered to the right method and easily consumable in the form of a given JAXB bean instance, then the possibility is that this code can work equally well when the data comes to this resource handler either via HTTP or JMS or indeed some other transport, example, CXF Local Transport.
CXF is super-flexible in the way it can support multiple transports, and it does make sense to get JAX-RS based endpoints optionally supporting non-HTTP transports.
And it is exactly for the same reason that CXF JAX-RS proxies (and I have to admit, WebClient :-) - simply because proxies and WebClient are using the same base code) also optionally support JMS transport now, thanks to the contribution from Willem.
So why would one want to use CXF JAX-RS client code with JMS ? As noted above, it is primarily about making the same code, client one in this case, re-usable in different contexts. I could've noted again that REST principles can probably be applied even to RS-232 endpoints if really really needed :-) but I'd rather focus on the re-usability aspect.
For example, consider a newly introduced HTTPSPStateManager implementation for making it easy for users to quickly set up a centralized distributed SSO cache endpoint. You've tested it and seen it working with HTTP. Now the time has come up for you to move to a more sophisticated distributed cache implementation for it to scale really well in the production. But then you realize that by simply getting HTTPSPStateManager proxies and the endpoint addresses use a JMS scheme you can get an entirely different cache support, still using the same configuration, so you are going to give it a go and see what happens.
Or perhaps you have a Camel JAX-RS endpoint, supported by Camel transport and jaxrs:endpoint or CXFRS bean or endpoint, supporting both HTTP and JMS. It would be cool to get the same Camel CXFRS client to be able to talk to the endpoints using either HTTP or JMS.
I'm hoping users can come up with more interesting cases which will be possible thanks to the optional end-to-end support for JMS in the JAX-RS frontend.
Enjoy!
The main reason behind making the JAX-RS frontend (associated by most users with supporting HTTP-based communications) JMS-aware was to do with getting the most from the 'investment' made into implementing the RESTful services on top of CXF JAX-RS.
If one has the resource code relying on the JAX-RS runtime to make the inbound data delivered to the right method and easily consumable in the form of a given JAXB bean instance, then the possibility is that this code can work equally well when the data comes to this resource handler either via HTTP or JMS or indeed some other transport, example, CXF Local Transport.
CXF is super-flexible in the way it can support multiple transports, and it does make sense to get JAX-RS based endpoints optionally supporting non-HTTP transports.
And it is exactly for the same reason that CXF JAX-RS proxies (and I have to admit, WebClient :-) - simply because proxies and WebClient are using the same base code) also optionally support JMS transport now, thanks to the contribution from Willem.
So why would one want to use CXF JAX-RS client code with JMS ? As noted above, it is primarily about making the same code, client one in this case, re-usable in different contexts. I could've noted again that REST principles can probably be applied even to RS-232 endpoints if really really needed :-) but I'd rather focus on the re-usability aspect.
For example, consider a newly introduced HTTPSPStateManager implementation for making it easy for users to quickly set up a centralized distributed SSO cache endpoint. You've tested it and seen it working with HTTP. Now the time has come up for you to move to a more sophisticated distributed cache implementation for it to scale really well in the production. But then you realize that by simply getting HTTPSPStateManager proxies and the endpoint addresses use a JMS scheme you can get an entirely different cache support, still using the same configuration, so you are going to give it a go and see what happens.
Or perhaps you have a Camel JAX-RS endpoint, supported by Camel transport and jaxrs:endpoint or CXFRS bean or endpoint, supporting both HTTP and JMS. It would be cool to get the same Camel CXFRS client to be able to talk to the endpoints using either HTTP or JMS.
I'm hoping users can come up with more interesting cases which will be possible thanks to the optional end-to-end support for JMS in the JAX-RS frontend.
Enjoy!
Subscribe to:
Posts (Atom)